library(coda)
library(bayesplot) 
library(ggplot2)
library(ggsci)
library(khroma)
library(tidyverse)
library(reshape2)
library(here)
knitr::opts_chunk$set(echo = TRUE, dpi = 300 )

Set up MCSim file

# this markdown file must be saved in top level directory for the following to work; the mcsim code depends on getwd results.
mdir <- "MCSim"
source(here::here(mdir,"setup_MCSim.R"))
# Make mod.exe (used to create mcsim executable from model file)
makemod() 
The mod.exe had been created.

Set filenames and load data

Set up dataset

id_lut <- multicheck$df_check %>% select(Level) %>% unique ()  %>%
  mutate(dataset = c( 
    rep("Decatur M Train", 9),
    rep("Decatur F Train", 9),
    rep("Decatur M Test", 9),
    rep("Decatur F Test", 10),
    'Paulsboro-Train','Horsham-Train',
    'Warminster-Test','Warrington-Train'), 
    Sex = c( 
    rep("M", 9),
    rep("F", 9),
    rep("M", 9),
    rep("F", 10),
    'Mixed', 'Mixed',  'Mixed', 'Mixed'),
    City = c( 
    rep("Decatur", 18),
    rep("Decatur", 19),
    'Paulsboro','Horsham','Warminster','Warrington'), 
    Train_Test = c( 
    rep("Train", 9),
    rep("Train", 9),
    rep("Test", 9),
    rep("Test", 10),
    'Train', 'Train', 'Test', 'Test'),
    datatype = c(
      rep("Individual",9+9+9+10),
      rep("Summary",4)),
    Simulation = row_number(),
    variable = paste0(dataset, " ",Simulation))

id_lut$dataset <- factor(id_lut$dataset,levels=
                           c("Decatur M Train","Decatur F Train","Arnsberg M Train",
                             "Arnsberg F Train","Decatur M Test","Decatur F Test","Arnsberg M Test",
                             "Arnsberg F Test","Minnesota Train","Minnesota Test",
                             'Lubeck-Bartell-Train', 'Lubeck-Bartell-Test',
                             'Little Hocking-Bartell-Train', 'Little Hocking-Bartell-Test',
                             'Little Hocking-Emmett-Test','Paulsboro-Train','Horsham-Train',
                             'Warminster-Test','Warrington-Train'))
id_lut$City <- factor(id_lut$City,levels = 
                        c("Decatur","Arnsberg","Minnesota",'Lubeck-Bartell',
                          'Little Hocking-Bartell','Little Hocking-Emmett',
                          'Paulsboro','Horsham','Warminster','Warrington'))
 

indiv_lut <- id_lut %>% 
  filter(City %in% c("Decatur")) %>%
  mutate(  dataset = as.factor(dataset))

nv <- data.frame(dataset =unique(indiv_lut$dataset), 
           variable= rep("Pop GM", 4),
           type= rep("Pop GM", 4), stringsAsFactors = FALSE)

Scatter plot of predictions (median of multicheck samples) versus data.

This is a Figure 2 panel. Needed to use “scale=1.1” in ggsave to match PFOA.

nrow(multicheck$df_check)
[1] 39000
nrow(id_lut)
[1] 41
multicheck$df_check %>% left_join(id_lut) %>% nrow()
Joining, by = c("Level", "Simulation")
[1] 39000
names(multicheck$df_check)
[1] "Level"      "Simulation" "Output_Var" "Time"       "Data"      
[6] "Prediction"
Level

Simulation

Output_Var

Time

Data

Prediction
multicheck2 <- multicheck$df_check %>% 
  left_join(id_lut, by = c("Level", "Simulation"))%>% 
  group_by_at ( vars(-Prediction)) %>% 
  summarise(Prediction = median(Prediction)) %>%
  ungroup() %>%
  group_by(City) %>% 
  mutate(Train_Test = factor(Train_Test, levels = c("Train", "Test")),
         `City (datatype)` = factor (paste0(City, "\n(", datatype, ")\n") ),
         label = case_when(Train_Test=="Train" ~ "G: PFHxS Train",
                           Train_Test=="Test"  ~ "H: PFHxS Test",
                           TRUE ~ ""))
Warning in mutate_impl(.data, dots, caller_env()): Unequal factor levels:
coercing to character
Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector
#define color for testing boxplots
bp_cols <- c (as.character (khroma::colour("muted")(9)) , "#191919")   
bp_cols <-bp_cols[c(1,7,10:8)]# plot_scheme_colourblind(bp_cols) 

### Create aesthetics lookup
aes_lut <- multicheck2 %>% ungroup() %>% 
  group_by(City, datatype,  `City (datatype)` ) %>% summarise () %>% ungroup() %>%
  mutate( cols = bp_cols, city_fills =   bp_cols , 
          # for individual level on point plot (multicheck2), darken outlines for visibility, use standard colors otherwise
         city_outlines =  if_else(datatype == "Individual"  ,  colorspace::darken(city_fills, 0.3), city_fills) ,  
         shapes = case_when(datatype == "Individual"  & `City` %in% c('Decatur', 'Arnsberg', 'Minnesota')   ~  23,
                            datatype == "Summary" &`City` %in% c("Horsham", "Warminster",  "Warrington") ~ 2,
                            datatype == "Summary" & `City` == "Paulsboro" ~ 1,
                            TRUE ~ 18                                ), 
         size = if_else(datatype =="Individual", 1.75, 2.5 ) )  



source( paste0(gsub(basename(here()), 'shared_functions', here()), '/plot_scatter_mcheck.r'))

p2 <- plot_scatter_mcheck(dframe = multicheck2,  pfas_nom = pfas_name, aes_lut_fn = aes_lut )
print(p2) 

ggsave(here ("output-plots", paste0( sa,"multicheckplot_", pfas_name,
               ".pdf")),p2,dpi=600, scale=1.1)
Saving 8.8 x 3.85 in image

Parse multicheck

df_check <- multicheck$df_check
df_check <- subset(df_check,Data > 0) 

n1 <- nrow(df_check)
id_chks <- df_check %>% select(Level) %>% unique() %>% bind_cols(id_lut)  %>%
  mutate(dataset = as.factor(dataset), Sex = as.factor(Sex), City = as.factor(City), 
         Train_Test = as.factor(Train_Test))

df_check <- df_check %>% left_join(id_chks)%>%
  mutate(Dataset = paste(as.character(dataset), Simulation),
         Sex = ordered(Sex, levels = c("M", "F", "Mixed"), 
                       labels = c("Male", "Female", "Mixed (all sexes)")))
Joining, by = c("Level", "Simulation")
n2 <- nrow(df_check)
if(n1 != n2)print("duplicates created in id-lut join")
df_check$Time.desc <- as.character(paste0("T=",df_check$Time))
df_check$Time.desc[df_check$Time.desc == "T=1e-06"] <- "SteadyState"
df_check$Dataset.Time <- interaction(df_check$Dataset,
                                     df_check$Time.desc,lex.order=TRUE)
df_check$Dataset.Time <- factor(df_check$Dataset.Time,
                                levels=levels(df_check$Dataset.Time))
calibdata <- df_check[,names(df_check) != "Prediction"]
calibdata <- calibdata[!duplicated(calibdata),]
print(calibdata)
        Level Simulation Output_Var  Time   Data     Level1          dataset
1   1_1_1_1_1          1     Cserum 0.000 15.400  1_1_1_1_1  Decatur M Train
2   1_1_1_1_1          1     Cserum 5.802 16.600  1_1_1_1_1  Decatur M Train
3   1_1_1_1_2          2     Cserum 0.000  4.900  1_1_1_1_2  Decatur M Train
4   1_1_1_1_2          2     Cserum 5.802  6.100  1_1_1_1_2  Decatur M Train
5   1_1_1_1_3          3     Cserum 0.000 11.300  1_1_1_1_3  Decatur M Train
6   1_1_1_1_3          3     Cserum 5.802  7.800  1_1_1_1_3  Decatur M Train
7   1_1_1_1_4          4     Cserum 0.000 12.800  1_1_1_1_4  Decatur M Train
8   1_1_1_1_4          4     Cserum 5.802  5.600  1_1_1_1_4  Decatur M Train
9   1_1_1_1_5          5     Cserum 0.000 20.900  1_1_1_1_5  Decatur M Train
10  1_1_1_1_5          5     Cserum 5.802 12.400  1_1_1_1_5  Decatur M Train
11  1_1_1_1_6          6     Cserum 0.000  6.300  1_1_1_1_6  Decatur M Train
12  1_1_1_1_6          6     Cserum 5.802  6.700  1_1_1_1_6  Decatur M Train
13  1_1_1_1_7          7     Cserum 0.000 24.400  1_1_1_1_7  Decatur M Train
14  1_1_1_1_7          7     Cserum 5.802 18.100  1_1_1_1_7  Decatur M Train
15  1_1_1_1_8          8     Cserum 0.000 24.200  1_1_1_1_8  Decatur M Train
16  1_1_1_1_8          8     Cserum 5.802 20.200  1_1_1_1_8  Decatur M Train
17  1_1_1_1_9          9     Cserum 0.000  7.800  1_1_1_1_9  Decatur M Train
18  1_1_1_1_9          9     Cserum 5.802  8.500  1_1_1_1_9  Decatur M Train
19 1_1_1_1_10         10     Cserum 0.000  2.300 1_1_1_1_10  Decatur F Train
20 1_1_1_1_10         10     Cserum 5.802  2.500 1_1_1_1_10  Decatur F Train
21 1_1_1_1_11         11     Cserum 0.000 12.900 1_1_1_1_11  Decatur F Train
22 1_1_1_1_11         11     Cserum 5.802 13.700 1_1_1_1_11  Decatur F Train
23 1_1_1_1_12         12     Cserum 0.000  2.400 1_1_1_1_12  Decatur F Train
24 1_1_1_1_12         12     Cserum 5.802  3.300 1_1_1_1_12  Decatur F Train
25 1_1_1_1_13         13     Cserum 0.000  2.700 1_1_1_1_13  Decatur F Train
26 1_1_1_1_13         13     Cserum 5.802  4.000 1_1_1_1_13  Decatur F Train
27 1_1_1_1_14         14     Cserum 0.000 18.300 1_1_1_1_14  Decatur F Train
28 1_1_1_1_14         14     Cserum 5.802 18.400 1_1_1_1_14  Decatur F Train
29 1_1_1_1_15         15     Cserum 0.000 12.900 1_1_1_1_15  Decatur F Train
30 1_1_1_1_15         15     Cserum 5.802 13.200 1_1_1_1_15  Decatur F Train
31 1_1_1_1_16         16     Cserum 0.000  3.300 1_1_1_1_16  Decatur F Train
32 1_1_1_1_16         16     Cserum 5.802  4.100 1_1_1_1_16  Decatur F Train
33 1_1_1_1_17         17     Cserum 0.000 16.900 1_1_1_1_17  Decatur F Train
34 1_1_1_1_17         17     Cserum 5.802 12.300 1_1_1_1_17  Decatur F Train
35 1_1_1_1_18         18     Cserum 0.000  8.700 1_1_1_1_18  Decatur F Train
36 1_1_1_1_18         18     Cserum 5.802  6.500 1_1_1_1_18  Decatur F Train
37  1_1_1_2_1         19     Cserum 0.000  6.300  1_1_1_2_1   Decatur M Test
38  1_1_1_2_1         19     Cserum 5.802  4.600  1_1_1_2_1   Decatur M Test
39  1_1_1_2_2         20     Cserum 0.000  7.100  1_1_1_2_2   Decatur M Test
40  1_1_1_2_2         20     Cserum 5.802  7.400  1_1_1_2_2   Decatur M Test
41  1_1_1_2_3         21     Cserum 0.000 19.500  1_1_1_2_3   Decatur M Test
42  1_1_1_2_3         21     Cserum 5.802 14.000  1_1_1_2_3   Decatur M Test
43  1_1_1_2_4         22     Cserum 0.000  7.500  1_1_1_2_4   Decatur M Test
44  1_1_1_2_4         22     Cserum 5.802  9.000  1_1_1_2_4   Decatur M Test
45  1_1_1_2_5         23     Cserum 0.000  8.600  1_1_1_2_5   Decatur M Test
46  1_1_1_2_5         23     Cserum 5.802  9.200  1_1_1_2_5   Decatur M Test
47  1_1_1_2_6         24     Cserum 0.000 12.400  1_1_1_2_6   Decatur M Test
48  1_1_1_2_6         24     Cserum 5.802 12.800  1_1_1_2_6   Decatur M Test
49  1_1_1_2_7         25     Cserum 0.000  8.900  1_1_1_2_7   Decatur M Test
50  1_1_1_2_7         25     Cserum 5.802  6.600  1_1_1_2_7   Decatur M Test
51  1_1_1_2_8         26     Cserum 0.000  7.400  1_1_1_2_8   Decatur M Test
52  1_1_1_2_8         26     Cserum 5.802  6.300  1_1_1_2_8   Decatur M Test
53  1_1_1_2_9         27     Cserum 0.000 14.300  1_1_1_2_9   Decatur M Test
54  1_1_1_2_9         27     Cserum 5.802 15.800  1_1_1_2_9   Decatur M Test
55 1_1_1_2_10         28     Cserum 0.000  3.800 1_1_1_2_10   Decatur F Test
56 1_1_1_2_10         28     Cserum 5.802  4.200 1_1_1_2_10   Decatur F Test
57 1_1_1_2_11         29     Cserum 0.000 22.100 1_1_1_2_11   Decatur F Test
58 1_1_1_2_11         29     Cserum 5.802 26.000 1_1_1_2_11   Decatur F Test
59 1_1_1_2_12         30     Cserum 0.000  6.500 1_1_1_2_12   Decatur F Test
60 1_1_1_2_12         30     Cserum 5.802  5.800 1_1_1_2_12   Decatur F Test
61 1_1_1_2_13         31     Cserum 0.000  7.500 1_1_1_2_13   Decatur F Test
62 1_1_1_2_13         31     Cserum 5.802  7.900 1_1_1_2_13   Decatur F Test
63 1_1_1_2_14         32     Cserum 0.000  7.500 1_1_1_2_14   Decatur F Test
64 1_1_1_2_14         32     Cserum 5.802  6.800 1_1_1_2_14   Decatur F Test
65 1_1_1_2_15         33     Cserum 0.000  7.500 1_1_1_2_15   Decatur F Test
66 1_1_1_2_15         33     Cserum 5.802  2.400 1_1_1_2_15   Decatur F Test
67 1_1_1_2_16         34     Cserum 0.000  6.000 1_1_1_2_16   Decatur F Test
68 1_1_1_2_16         34     Cserum 5.802  6.800 1_1_1_2_16   Decatur F Test
69 1_1_1_2_17         35     Cserum 0.000 18.200 1_1_1_2_17   Decatur F Test
70 1_1_1_2_17         35     Cserum 5.802 13.200 1_1_1_2_17   Decatur F Test
71 1_1_1_2_18         36     Cserum 0.000  5.300 1_1_1_2_18   Decatur F Test
72 1_1_1_2_18         36     Cserum 5.802  3.900 1_1_1_2_18   Decatur F Test
73 1_1_1_2_19         37     Cserum 0.000  5.600 1_1_1_2_19   Decatur F Test
74 1_1_1_2_19         37     Cserum 5.802  5.400 1_1_1_2_19   Decatur F Test
75      1_2_1         38 M_Cbgd_Css 2.200  2.593      1_2_1  Paulsboro-Train
76      1_3_1         39 M_Cbgd_Css 2.000 27.340      1_3_1    Horsham-Train
77      1_4_1         40 M_Cbgd_Css 2.000 23.157      1_4_1  Warminster-Test
78    1_4_2_1         41 M_Cbgd_Css 2.000 14.851    1_4_2_1 Warrington-Train
                 Sex       City Train_Test   datatype            variable
1               Male    Decatur      Train Individual   Decatur M Train 1
2               Male    Decatur      Train Individual   Decatur M Train 1
3               Male    Decatur      Train Individual   Decatur M Train 2
4               Male    Decatur      Train Individual   Decatur M Train 2
5               Male    Decatur      Train Individual   Decatur M Train 3
6               Male    Decatur      Train Individual   Decatur M Train 3
7               Male    Decatur      Train Individual   Decatur M Train 4
8               Male    Decatur      Train Individual   Decatur M Train 4
9               Male    Decatur      Train Individual   Decatur M Train 5
10              Male    Decatur      Train Individual   Decatur M Train 5
11              Male    Decatur      Train Individual   Decatur M Train 6
12              Male    Decatur      Train Individual   Decatur M Train 6
13              Male    Decatur      Train Individual   Decatur M Train 7
14              Male    Decatur      Train Individual   Decatur M Train 7
15              Male    Decatur      Train Individual   Decatur M Train 8
16              Male    Decatur      Train Individual   Decatur M Train 8
17              Male    Decatur      Train Individual   Decatur M Train 9
18              Male    Decatur      Train Individual   Decatur M Train 9
19            Female    Decatur      Train Individual  Decatur F Train 10
20            Female    Decatur      Train Individual  Decatur F Train 10
21            Female    Decatur      Train Individual  Decatur F Train 11
22            Female    Decatur      Train Individual  Decatur F Train 11
23            Female    Decatur      Train Individual  Decatur F Train 12
24            Female    Decatur      Train Individual  Decatur F Train 12
25            Female    Decatur      Train Individual  Decatur F Train 13
26            Female    Decatur      Train Individual  Decatur F Train 13
27            Female    Decatur      Train Individual  Decatur F Train 14
28            Female    Decatur      Train Individual  Decatur F Train 14
29            Female    Decatur      Train Individual  Decatur F Train 15
30            Female    Decatur      Train Individual  Decatur F Train 15
31            Female    Decatur      Train Individual  Decatur F Train 16
32            Female    Decatur      Train Individual  Decatur F Train 16
33            Female    Decatur      Train Individual  Decatur F Train 17
34            Female    Decatur      Train Individual  Decatur F Train 17
35            Female    Decatur      Train Individual  Decatur F Train 18
36            Female    Decatur      Train Individual  Decatur F Train 18
37              Male    Decatur       Test Individual   Decatur M Test 19
38              Male    Decatur       Test Individual   Decatur M Test 19
39              Male    Decatur       Test Individual   Decatur M Test 20
40              Male    Decatur       Test Individual   Decatur M Test 20
41              Male    Decatur       Test Individual   Decatur M Test 21
42              Male    Decatur       Test Individual   Decatur M Test 21
43              Male    Decatur       Test Individual   Decatur M Test 22
44              Male    Decatur       Test Individual   Decatur M Test 22
45              Male    Decatur       Test Individual   Decatur M Test 23
46              Male    Decatur       Test Individual   Decatur M Test 23
47              Male    Decatur       Test Individual   Decatur M Test 24
48              Male    Decatur       Test Individual   Decatur M Test 24
49              Male    Decatur       Test Individual   Decatur M Test 25
50              Male    Decatur       Test Individual   Decatur M Test 25
51              Male    Decatur       Test Individual   Decatur M Test 26
52              Male    Decatur       Test Individual   Decatur M Test 26
53              Male    Decatur       Test Individual   Decatur M Test 27
54              Male    Decatur       Test Individual   Decatur M Test 27
55            Female    Decatur       Test Individual   Decatur F Test 28
56            Female    Decatur       Test Individual   Decatur F Test 28
57            Female    Decatur       Test Individual   Decatur F Test 29
58            Female    Decatur       Test Individual   Decatur F Test 29
59            Female    Decatur       Test Individual   Decatur F Test 30
60            Female    Decatur       Test Individual   Decatur F Test 30
61            Female    Decatur       Test Individual   Decatur F Test 31
62            Female    Decatur       Test Individual   Decatur F Test 31
63            Female    Decatur       Test Individual   Decatur F Test 32
64            Female    Decatur       Test Individual   Decatur F Test 32
65            Female    Decatur       Test Individual   Decatur F Test 33
66            Female    Decatur       Test Individual   Decatur F Test 33
67            Female    Decatur       Test Individual   Decatur F Test 34
68            Female    Decatur       Test Individual   Decatur F Test 34
69            Female    Decatur       Test Individual   Decatur F Test 35
70            Female    Decatur       Test Individual   Decatur F Test 35
71            Female    Decatur       Test Individual   Decatur F Test 36
72            Female    Decatur       Test Individual   Decatur F Test 36
73            Female    Decatur       Test Individual   Decatur F Test 37
74            Female    Decatur       Test Individual   Decatur F Test 37
75 Mixed (all sexes)  Paulsboro      Train    Summary  Paulsboro-Train 38
76 Mixed (all sexes)    Horsham      Train    Summary    Horsham-Train 39
77 Mixed (all sexes) Warminster       Test    Summary  Warminster-Test 40
78 Mixed (all sexes) Warrington       Test    Summary Warrington-Train 41
               Dataset Time.desc               Dataset.Time
1    Decatur M Train 1       T=0      Decatur M Train 1.T=0
2    Decatur M Train 1   T=5.802  Decatur M Train 1.T=5.802
3    Decatur M Train 2       T=0      Decatur M Train 2.T=0
4    Decatur M Train 2   T=5.802  Decatur M Train 2.T=5.802
5    Decatur M Train 3       T=0      Decatur M Train 3.T=0
6    Decatur M Train 3   T=5.802  Decatur M Train 3.T=5.802
7    Decatur M Train 4       T=0      Decatur M Train 4.T=0
8    Decatur M Train 4   T=5.802  Decatur M Train 4.T=5.802
9    Decatur M Train 5       T=0      Decatur M Train 5.T=0
10   Decatur M Train 5   T=5.802  Decatur M Train 5.T=5.802
11   Decatur M Train 6       T=0      Decatur M Train 6.T=0
12   Decatur M Train 6   T=5.802  Decatur M Train 6.T=5.802
13   Decatur M Train 7       T=0      Decatur M Train 7.T=0
14   Decatur M Train 7   T=5.802  Decatur M Train 7.T=5.802
15   Decatur M Train 8       T=0      Decatur M Train 8.T=0
16   Decatur M Train 8   T=5.802  Decatur M Train 8.T=5.802
17   Decatur M Train 9       T=0      Decatur M Train 9.T=0
18   Decatur M Train 9   T=5.802  Decatur M Train 9.T=5.802
19  Decatur F Train 10       T=0     Decatur F Train 10.T=0
20  Decatur F Train 10   T=5.802 Decatur F Train 10.T=5.802
21  Decatur F Train 11       T=0     Decatur F Train 11.T=0
22  Decatur F Train 11   T=5.802 Decatur F Train 11.T=5.802
23  Decatur F Train 12       T=0     Decatur F Train 12.T=0
24  Decatur F Train 12   T=5.802 Decatur F Train 12.T=5.802
25  Decatur F Train 13       T=0     Decatur F Train 13.T=0
26  Decatur F Train 13   T=5.802 Decatur F Train 13.T=5.802
27  Decatur F Train 14       T=0     Decatur F Train 14.T=0
28  Decatur F Train 14   T=5.802 Decatur F Train 14.T=5.802
29  Decatur F Train 15       T=0     Decatur F Train 15.T=0
30  Decatur F Train 15   T=5.802 Decatur F Train 15.T=5.802
31  Decatur F Train 16       T=0     Decatur F Train 16.T=0
32  Decatur F Train 16   T=5.802 Decatur F Train 16.T=5.802
33  Decatur F Train 17       T=0     Decatur F Train 17.T=0
34  Decatur F Train 17   T=5.802 Decatur F Train 17.T=5.802
35  Decatur F Train 18       T=0     Decatur F Train 18.T=0
36  Decatur F Train 18   T=5.802 Decatur F Train 18.T=5.802
37   Decatur M Test 19       T=0      Decatur M Test 19.T=0
38   Decatur M Test 19   T=5.802  Decatur M Test 19.T=5.802
39   Decatur M Test 20       T=0      Decatur M Test 20.T=0
40   Decatur M Test 20   T=5.802  Decatur M Test 20.T=5.802
41   Decatur M Test 21       T=0      Decatur M Test 21.T=0
42   Decatur M Test 21   T=5.802  Decatur M Test 21.T=5.802
43   Decatur M Test 22       T=0      Decatur M Test 22.T=0
44   Decatur M Test 22   T=5.802  Decatur M Test 22.T=5.802
45   Decatur M Test 23       T=0      Decatur M Test 23.T=0
46   Decatur M Test 23   T=5.802  Decatur M Test 23.T=5.802
47   Decatur M Test 24       T=0      Decatur M Test 24.T=0
48   Decatur M Test 24   T=5.802  Decatur M Test 24.T=5.802
49   Decatur M Test 25       T=0      Decatur M Test 25.T=0
50   Decatur M Test 25   T=5.802  Decatur M Test 25.T=5.802
51   Decatur M Test 26       T=0      Decatur M Test 26.T=0
52   Decatur M Test 26   T=5.802  Decatur M Test 26.T=5.802
53   Decatur M Test 27       T=0      Decatur M Test 27.T=0
54   Decatur M Test 27   T=5.802  Decatur M Test 27.T=5.802
55   Decatur F Test 28       T=0      Decatur F Test 28.T=0
56   Decatur F Test 28   T=5.802  Decatur F Test 28.T=5.802
57   Decatur F Test 29       T=0      Decatur F Test 29.T=0
58   Decatur F Test 29   T=5.802  Decatur F Test 29.T=5.802
59   Decatur F Test 30       T=0      Decatur F Test 30.T=0
60   Decatur F Test 30   T=5.802  Decatur F Test 30.T=5.802
61   Decatur F Test 31       T=0      Decatur F Test 31.T=0
62   Decatur F Test 31   T=5.802  Decatur F Test 31.T=5.802
63   Decatur F Test 32       T=0      Decatur F Test 32.T=0
64   Decatur F Test 32   T=5.802  Decatur F Test 32.T=5.802
65   Decatur F Test 33       T=0      Decatur F Test 33.T=0
66   Decatur F Test 33   T=5.802  Decatur F Test 33.T=5.802
67   Decatur F Test 34       T=0      Decatur F Test 34.T=0
68   Decatur F Test 34   T=5.802  Decatur F Test 34.T=5.802
69   Decatur F Test 35       T=0      Decatur F Test 35.T=0
70   Decatur F Test 35   T=5.802  Decatur F Test 35.T=5.802
71   Decatur F Test 36       T=0      Decatur F Test 36.T=0
72   Decatur F Test 36   T=5.802  Decatur F Test 36.T=5.802
73   Decatur F Test 37       T=0      Decatur F Test 37.T=0
74   Decatur F Test 37   T=5.802  Decatur F Test 37.T=5.802
75  Paulsboro-Train 38     T=2.2   Paulsboro-Train 38.T=2.2
76    Horsham-Train 39       T=2       Horsham-Train 39.T=2
77  Warminster-Test 40       T=2     Warminster-Test 40.T=2
78 Warrington-Train 41       T=2    Warrington-Train 41.T=2
#Multicheck plot

# Split Steady State Group into different populations for boxplot grouping
#df_check[df_check$Time.desc == "SteadyState" & grepl("Lubeck",df_check$Dataset),]$Time.desc <- "Lubeck"
#df_check[df_check$Time.desc == "SteadyState" & grepl("Little Hocking",df_check$Dataset),]$Time.desc <- "Little Hocking"

Modify aesthetics lookup table for boxplots

##  additional source aesthetic lookup table for grey-scale time (years);  merged legends save space on plotting output
times <- df_check%>% select(Time.desc, Time) %>%  unique () %>% 
  mutate(rank = rank(Time) , grey = grey.colors(start=1,end=0.4, n = n()),
         alpha = (rank)/8) %>% 
  select(-Time)
 
df_check <- df_check %>% mutate (legend_label = (paste0(City, "\n", Time.desc ) )) # add legend-labels
aes_lut <- df_check %>% 
  select(City, Train_Test, datatype,Time, Time.desc, legend_label) %>% unique () %>%
   left_join(aes_lut[, c("City", "cols")], by = "City") %>% ungroup () %>% unique ()%>%
   left_join (times, by = "Time.desc") %>% 
   arrange(datatype, City, Train_Test, Time)    %>% 
   mutate(alpha = if_else(City == "Horsham", alpha/2, alpha)) %>% # otherwise too dark with this color
  mutate_if(is.factor, as.character) 

Decatur boxplots

Changed grey start to 1 instead of 0.8, end at 0.6 instead of 0.4. Changed shape of symbols so they are filled.

#GH
# Decatur 

df_decat  <- df_check %>%   
  filter(City == "Decatur" & Train_Test %in% c ("Train", "Test")) %>% 
  mutate(panel = ordered (Train_Test, levels = c ("Train", "Test"), 
                          labels = c("G: PFHxS Decatur Train", "H: PFHxS Decatur Test") ))

aes_lut_df_df_decat <- aes_lut %>% 
  filter(City == "Decatur" & Train_Test %in% c ("Train", "Test")) %>% 
  mutate_if(is.factor, as.character) 

source( paste0(gsub(basename(here()), 'shared_functions', here()), '/plot_sum_boxplot.r'))


plt_train <- plot_sum_boxplot   (dframe = df_decat, aes_lut= aes_lut_df_df_decat, facets = TRUE , pfas_nom = pfas_name     ) 
print(plt_train)

ggsave(here ("output-plots",paste0( sa,"DecaturTrainTestboxplot",pfas_name,".pdf")),plt_train,dpi=600)
Saving 6.5 x 3.5 in image

All boxplots

Changed grey start to 1 instead of 0.8, end at 0.6 instead of 0.4. Added shapes and fills to data points.

lets <- LETTERS;
names(lets)[1:(length(unique(df_check$dataset))-4)]<-as.character(unique(df_check$dataset))[5:length(unique(df_check$dataset))]

for (d in unique(df_check$dataset)) { # d = unique(df_check$dataset)[11]
    ddset <- df_check %>%    
    filter(dataset == d) 
    
    aes_lut_ddset <- ddset %>% select(legend_label,  City,Train_Test,datatype, Time.desc  ) %>% unique () %>% inner_join(aes_lut)
      
    gt <- ifelse(is.na(lets[d]),d,paste0(lets[d],": ", d))
    plt <- plot_sum_boxplot(dframe = ddset, aes_lut= aes_lut_ddset, gtitle= gt, facets = FALSE, pfas_nom = pfas_name)
     
  print(plt)
  ggsave(here ("output-plots",
                paste0( sa, d,"-boxplot-", 
                pfas_name,".pdf")) ,
         plt,dpi=600)

}
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector
Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector
Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image

### make Training plot  

df_d_trt <- df_check %>%   
     filter( (Train_Test == "Train") & ((Output_Var == "M_Cbgd_Css") | (Output_Var == "M_Cserum"))) %>%
     mutate_if(is.factor, as.character) %>%  # drop factor levels unused
     mutate(Dataset.Time = factor(Dataset.Time)) 
 

 aes_lut_df_d_trt <-  df_d_trt %>% select(City, datatype,Time, Time.desc, legend_label) %>% 
   inner_join(aes_lut  ) %>% 
   select(-Train_Test) %>% ungroup () %>% unique ()  
Joining, by = c("City", "datatype", "Time", "Time.desc", "legend_label")
plt_train <-    plot_sum_boxplot(dframe = df_d_trt, aes_lut= aes_lut_df_d_trt,   
                                 gtitle="A: Summary Data - Train" , facets = FALSE, 
                                 pfas_nom = pfas_name )
  print(plt_train)

  ggsave(here ("output-plots", paste0( sa, "SummaryTrainDataboxplot",pfas_name,".pdf")), plt_train,dpi=600)
Saving 6.5 x 3.5 in image
###  make Test plot
df_d_test <- df_check %>%   
    filter((Train_Test == "Test") & 
             ((Output_Var == "M_Cbgd_Css") | (Output_Var == "M_Cserum")))  %>%
     mutate_if(is.factor, as.character) %>%  # drop factor levels unused
     mutate(Dataset.Time = factor(Dataset.Time)) 

aes_lut_df_d_test <-  df_d_test %>% select(City, datatype,Time, Time.desc, legend_label) %>% 
   inner_join(aes_lut  ) %>% 
   select(-Train_Test) %>% ungroup () %>% unique ()  
Joining, by = c("City", "datatype", "Time", "Time.desc", "legend_label")
plt_test <- plot_sum_boxplot(dframe = df_d_test, aes_lut= aes_lut_df_d_test, 
                             gtitle="B: Summary Data - Test", facets = FALSE, pfas_nom = pfas_name)
  print(plt_test)

  ggsave(here ("output-plots",paste0( sa, "SummaryTestDataboxplot",pfas_name,".pdf")), plt_test,dpi=600) 
Saving 6.5 x 3.5 in image

PFHxS

Background posteriors

Shows shift in background estimate.

gmscale<-0.8

dat <- multicheck$parms.samp[,grep("M_ln_Cbgd",names(multicheck$parms.samp))]
datasetnames <- as.character(unique(calibdata$dataset))
datasetnames <- gsub(" Train","-Train",datasetnames)
datasetnames <- gsub(" Test","-Train",datasetnames)
datasetnames <- gsub(" M","",datasetnames)
datasetnames <- gsub(" F","",datasetnames)
datasetnames<-datasetnames[!duplicated(datasetnames)]
datasetnames <- datasetnames[grep("Train",datasetnames)]
names(dat) <- datasetnames
dat <- dat[,grep("Train",names(dat))]
dat.df <- pivot_longer(dat,1:ncol(dat))
dat.df <- rbind(dat.df,
                data.frame(name="Prior",value=rnorm(5000,m=log(gmscale),sd=0.4055)))
dat.df$name <- factor(dat.df$name,levels=rev(
                        c("Prior",datasetnames[grep("Train",datasetnames)])))
dat.df$value <- exp(dat.df$value)

p<-ggplot(dat.df)+
 # geom_violin(aes(x=name,y=value,fill=name=="Prior"))+
  geom_boxplot(aes(x=name,y=value,fill=name=="Prior"),outlier.shape=NA)+
  scale_y_log10()+coord_flip()+
  scale_fill_manual(name=NULL, 
                    values=c("#009988", "#EE7733" )) +
  theme_classic() +  
  theme(axis.title.y.left = element_blank())+
  geom_hline(yintercept = gmscale, color="darkgrey", linetype = 2, size = 1.25)+
  theme(legend.position="none",
      panel.background = element_rect(color="black",size=1))+
  ylab("Posterior shift in Background Concentration")

print(p)

ggsave(here ("output-plots",paste0( sa, "PFHxS_GM_Cbgd.pdf")) ,p,dpi=600)
Saving 5 x 6 in image

Half-life

For PFHxS, the population GM of the half-life has a posterior distribution that is narrower than the prior, with a posterior median (95% CI) estimate of 3.06 (2.16-4.37) years. The population GSD posterior is larger than the prior at 1.47(1.44-1.75).

dat <- multicheck$parms.samp[,c("M_ln_k.1.","V_ln_k.1.", "M_ln_Vd.1.", "SD_ln_Vd.1.")]
names(dat) <- c("M_ln_k(1)","V_ln_k(1)", "M_ln_Vd(1)", "SD_ln_Vd(1)")
  
set.seed(3.14159)
dat$z_ln_k <- rnorm(nrow(dat))
dat$z_ln_Vd <- rnorm(nrow(dat))
dat %>% rename_()
dat$ln_k_i <- dat$`M_ln_k(1)` + sqrt(dat$`V_ln_k(1)`)*dat$z_ln_k
dat$ln_Vd_i <- dat$`M_ln_Vd(1)`+ dat$`SD_ln_Vd(1)`*dat$z_ln_Vd
linmod <- lm(ln_Vd_i ~ ln_k_i,data=dat)
ggplot(dat) + geom_point(aes(ln_k_i,ln_Vd_i)) + 
  labs(subtitle=paste("Adj R2 =",signif(summary(linmod)$adj.r.squared,2)))

Check normality

qqnorm(dat$ln_k_i,main="ln k Q-Q Normal")
qqline(dat$ln_k_i,col="red")

plot(ecdf(dat$ln_k_i))
x <- seq(-3,1,0.01)
m_ln_k_i <-   mean(dat$ln_k_i)
sd_ln_k_i <- sd(dat$ln_k_i)
lines(x,pnorm(x,mean=m_ln_k_i,sd=sd_ln_k_i),col="red")
text(m_ln_k_i-2*sd_ln_k_i,0.9,paste("m =",signif(m_ln_k_i,4),"\nsd =",signif(sd_ln_k_i,4)))

qqnorm(dat$ln_Vd_i,main="ln Vd Q-Q Normal")
qqline(dat$ln_Vd_i,col="red")

plot(ecdf(dat$ln_Vd_i))
x <- seq(-3,1,0.01)
m_ln_Vd_i <- mean(dat$ln_Vd_i)
sd_ln_Vd_i <- sd(dat$ln_Vd_i)

lines(x,pnorm(x,mean=m_ln_Vd_i,sd=sd_ln_Vd_i),col="red")
text(m_ln_Vd_i-2*sd_ln_Vd_i,0.9,paste("m =",signif(m_ln_Vd_i,4),"\nsd =",signif(sd_ln_Vd_i,4)))

Calculate table values for individual-level

hl_i <- log(2)/ exp(dat$ln_k_i) # individual half-life 
med_hl_i <- paste(signif (median (hl_i), 3)) # median of individual half-life
ci_med_hl_i <-   paste(signif (quantile(hl_i, prob=c(0.025,0.975)), 3),collapse="-") # 95ci med individual halflife
ci98_med_hl_i <-   paste(signif (quantile(hl_i, prob=c(0.01,0.99)), 3),collapse="-") # 98ci med individual halflife
gm_hl_i <- paste(signif (exp(mean(log(hl_i))), 3)) # gm (which should be really close)
gsd_hl_i <- paste(signif (exp(sd(log(hl_i))), 3)) # gsd individual

med_Vd_i <- paste(signif (median(exp(dat$ln_Vd_i)), 3)) # median individual Vd
ci_med_Vd_i <-paste(signif (quantile(exp(dat$ln_Vd_i), prob=c(0.025,0.975)), 3),collapse="-") # 95ci med individual Vd
ci98_med_Vd_i <-paste(signif (quantile(exp(dat$ln_Vd_i), prob=c(0.01,0.99)), 3),collapse="-") # 98ci med individual Vd
gm_vd_i <- paste(signif (exp(mean(dat$ln_Vd_i)), 3)) # gm (which should be really close)
gsd_vd_i<- paste(signif (exp(sd(dat$ln_Vd_i)), 3)) # gsd indiv
PFHxS_priors <- data.frame(
  halflife_GM= log(2)/rlnorm(50000,
                             meanlog=-2.03422,sdlog=0.4055))
M_k <- exp(as.numeric(dat$`M_ln_k(1)`))
PFHxS_halflife_GM <- log(2)/M_k

PFHxS_hlgm_pr_med <- signif(median(PFHxS_priors$halflife_GM,3))
PFHxS_hlgm_pr_med_95ci <-paste(signif(quantile(PFHxS_priors$halflife_GM,
                                            prob=c(0.025,0.975)),
                                   3),
                            collapse="-")

PFHxS_hl_median_gm <- signif(median(PFHxS_halflife_GM),3)
PFHxS_hl_median_gm_95ci <- paste(signif(quantile(PFHxS_halflife_GM,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(halflife_GM, color = "Prior"),data=PFHxS_priors,geom="line",size=2)+
  stat_density(aes(PFHxS_halflife_GM, stat(density),color="Posterior"),geom="line",size=1.5 )+
  xlim(0,15)+
  labs(title = bquote("G: PFHxS"~T[1/2]~"Population GM")  ,
       subtitle=paste("Posterior Median (95% CI): ",
                      PFHxS_hl_median_gm," (",
                      PFHxS_hl_median_gm_95ci,
                      ")",sep=""))+
  xlab(bquote("Population GM"~T[1/2]~"(yrs)")) +
  scale_color_manual(name=NULL,#
                    values=c(Prior="#009988", Posterior="#EE7733" )) + 
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)
Warning: Removed 250 rows containing non-finite values (stat_density).
Warning: Removed 6 rows containing non-finite values (stat_density).

ggsave(here ("output-plots",paste0( sa, "PFHxS_hl_gm.pdf")),p,dpi=600)
Saving 4 x 2.5 in image
Warning: Removed 250 rows containing non-finite values (stat_density).

Warning: Removed 6 rows containing non-finite values (stat_density).
PFHxS_priors$halflife_GSD =  exp(sqrt(exp(rnorm(50000,m=log(0.2),sd=log(1.275))))) 
PFHxS_halflife_GSD <- exp(sqrt(dat$`V_ln_k(1)`))

PFHxS_hlgsd_pr_med <- signif(median(PFHxS_priors$halflife_GSD,3))
PFHxS_hlgsd_pr_med_95ci <-paste(signif(quantile(PFHxS_priors$halflife_GSD,
                                            prob=c(0.025,0.975)),
                                   3),
                            collapse="-")
PFHxS_hl_gsd_med <- signif(median(PFHxS_halflife_GSD),3)
PFHxS_hl_gsd_med_95ci <- paste(signif(quantile(PFHxS_halflife_GSD,
                                            prob=c(0.025,0.975)),3),collapse="-")
p<-ggplot()+
  stat_density(aes(halflife_GSD, color = "Prior"),data=PFHxS_priors,geom="line", size=2)+
  stat_density(aes(PFHxS_halflife_GSD,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(1,3)+
  labs(title = bquote("H: PFHxS"~T[1/2]~"Population GSD"),  
       subtitle=paste("Posterior Median (95% CI): ",
                      PFHxS_hl_gsd_med," (",
                      PFHxS_hl_gsd_med_95ci,
                      ")",sep=""))+
  xlab(bquote("Population GSD"~T[1/2]))+
  scale_color_manual(name=NULL,#
                    values=c(Prior="#009988", Posterior="#EE7733" )) + 
   theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa, "PFHxS_hl_gsd.pdf")) ,p,dpi=600)

Volume of distribution

For PFHxS, the data were not particularly informative, but slightly increased the estimate of the median to 0.308(0.223-0.548) slightly compared to the case where Cbgd was considered to be entirely from non-drinking water sources. They were not informative as to the population GSD, with the posterior distributions essentially unchanged from the priors.

PFHxS_priors$Vd_GM <- rlnorm(50000,
                             meanlog=-1.38629,
                             sdlog=0.2624)
PFHxS_Vd_GM <- exp(dat$`M_ln_Vd(1)`)

 

PFHxS_vd_gm_pr_med <- signif(median(PFHxS_priors$Vd_GM,3))
PFHxS_vd_gm_pr_med_95ci <- paste(signif(quantile(PFHxS_priors$Vd_GM,
                                            prob=c(0.025,0.975)), 3), collapse="-")
PFHxS_vd_gm_med <- signif(median(PFHxS_Vd_GM),3)
PFHxS_vd_gm_med_95ci <- paste(signif(quantile(PFHxS_Vd_GM,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(Vd_GM, color = "Prior"),data=PFHxS_priors,geom="line",size=2)+
  stat_density(aes(PFHxS_Vd_GM,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(0,1)+labs(title = bquote("G: PFHxS"~V[d]~"Population GM"),
                 subtitle=paste("Posterior Median (95% CI): ",
                                PFHxS_vd_gm_med," (", 
                                PFHxS_vd_gm_med_95ci,")",sep=""))+
   xlab(bquote("Population GM"~V[d]~"(l/kg)"))+
  scale_color_manual(name=NULL,#
                    values=c(Prior="#009988", Posterior="#EE7733" )) +  
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa, "PFHxS_vd_gm.pdf")) ,p,dpi=600)
PFHxS_priors$Vd_GSD = exp(abs(rnorm(50000,sd=0.17)))
PFHxS_Vd_GSD <- exp(dat$`SD_ln_Vd(1)`)

PFHxS_vd_gsd_pr_med <- signif(median(PFHxS_priors$Vd_GSD,3))
PFHxS_vd_gsd_pr_med_95ci <- paste(signif(quantile(PFHxS_priors$Vd_GSD,
                                            prob=c(0.025,0.975)), 3), collapse="-")

PFHxS_vd_gsd_med <- signif(median(PFHxS_Vd_GSD),3)
PFHxS_vd_gsd_med_95ci <- paste(signif(quantile(PFHxS_Vd_GSD,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(Vd_GSD, color = "Prior"),data=PFHxS_priors,geom="line",size=2)+
  stat_density(aes(PFHxS_Vd_GSD,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(1,3)+
  labs(title = bquote("H: PFHxS"~V[d]~"Population GSD "),
       subtitle=paste("Posterior Median (95% CI): ",
                      PFHxS_vd_gsd_med," (",
                      PFHxS_vd_gsd_med_95ci,
                      ")",sep=""))+
  xlab(bquote("Population GSD"~V[d]))+
  scale_color_manual(name=NULL, 
                     values=c(Prior="#009988", Posterior="#EE7733" )) + 
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa,"PFHxS_vd_gsd.pdf")) ,p,dpi=600)

Clearance (just pop GM)

Cl is k * Vd

PFHxS_priors$CL_GM <- PFHxS_priors$Vd_GM * (log(2)/PFHxS_priors$halflife_GM)
PFHxS_CL_GM <- exp(dat$`M_ln_Vd(1)` + dat$`M_ln_k(1)`)

PFHxS_cl_gm_pr_med <- signif(median(PFHxS_priors$CL_GM,3))
PFHxS_cl_gm_pr_med_95ci <- paste(signif(quantile(PFHxS_priors$CL_GM,
                                            prob=c(0.025,0.975)), 3), collapse="-")
PFHxS_cl_gm_med <- signif(median(PFHxS_CL_GM),3)
PFHxS_cl_gm_med_95ci <- paste(signif(quantile(PFHxS_CL_GM,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(CL_GM, color = "Prior"),data=PFHxS_priors,geom="line",size=2)+
  stat_density(aes(PFHxS_CL_GM,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(0,0.25)+labs(title = "D: PFHxS Clearance Pop. GM ",subtitle=paste("Posterior Median (95% CI): ",
                                                                    PFHxS_cl_gm_med," (",
                                                                    PFHxS_cl_gm_med_95ci,
                                                                    ")",sep=""))+
  xlab("Pop. GM CL (l/(kg-yr))")+
  scale_color_manual(name=NULL,#
                    values=c(Prior="#009988", Posterior="#EE7733" )) +  
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa, "PFHxS_CL_gm.pdf")), p,dpi=600)

Table significant digit values

PFHxS_hlgm_pr_med <- paste(signif(PFHxS_hlgm_pr_med, 3))
PFHxS_hl_median_gm<- paste(signif(PFHxS_hl_median_gm, 3))
PFHxS_hlgsd_pr_med<- paste(signif(PFHxS_hlgsd_pr_med, 3))
PFHxS_hl_gsd_med<- paste(signif(PFHxS_hl_gsd_med, 3))
PFHxS_vd_gm_pr_med<- paste(signif(PFHxS_vd_gm_pr_med, 3))
PFHxS_vd_gm_med<- paste(signif(PFHxS_vd_gm_med, 3))
PFHxS_vd_gsd_pr_med<- paste(signif(PFHxS_vd_gsd_pr_med, 3))
PFHxS_vd_gsd_med<- paste(signif(PFHxS_vd_gsd_med, 3))
PFHxS_cl_gm_pr_med<- paste(signif(PFHxS_cl_gm_pr_med, 3))
PFHxS_cl_gm_med<- paste(signif(PFHxS_cl_gm_med, 3))

Population median estimates [95% CI]

Parameter Prior GM Posterior GM Prior GSD Posterior GSD
Half-life (years) 5.29 8.3 1.56 1.57
HL [95% CI] [2.39-11.8] [5.38-13.5] [1.42-1.77] [1.42-1.77]
Volume of distribution 0.25 0.286 1.12 1.11
\(V_D\) [95% CI] [0.149-0.418] [0.173-0.456] [1.01-1.46] [1-1.45]
Clearance 0.0326 0.0246
\(CL\) [95% CI] [0.0126-0.0847] [0.0121-0.0393] [] []

Individual Posterior estimates

Parameter median GM [95% CI] [[98% CI]] GM calculator input GSD individual
Half-life (years) 8.12 [ 2.79-21.6 ] [[ 2.19-24.8 ]] 8.2 1.68
Volume of distribution \(V_D\) 0.281 [ 0.161-0.46 ] [[ 0.14-0.561 ]] 0.281 1.32

Session information

─ Session info ───────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 3.6.1 (2019-07-05)
 os       Oracle Linux Server 7.9     
 system   x86_64, linux-gnu           
 ui       X11                         
 language (EN)                        
 collate  en_US.UTF-8                 
 ctype    en_US.UTF-8                 
 tz       America/New_York            
 date     2021-03-28                  

─ Packages ───────────────────────────────────────────────────────────────────
 package     * version date       lib source        
 assertthat    0.2.1   2019-03-21 [2] CRAN (R 3.6.1)
 backports     1.1.5   2019-10-02 [2] CRAN (R 3.6.1)
 base64enc     0.1-3   2015-07-28 [2] CRAN (R 3.6.1)
 bayesplot   * 1.7.0   2019-05-23 [2] CRAN (R 3.6.1)
 broom         0.5.2   2019-04-07 [2] CRAN (R 3.6.1)
 callr         3.3.2   2019-09-22 [2] CRAN (R 3.6.1)
 cellranger    1.1.0   2016-07-27 [2] CRAN (R 3.6.1)
 cli           1.1.0   2019-03-19 [2] CRAN (R 3.6.1)
 coda        * 0.19-3  2019-07-05 [2] CRAN (R 3.6.1)
 codetools     0.2-16  2018-12-24 [2] CRAN (R 3.6.1)
 colorspace    1.4-1   2019-03-18 [2] CRAN (R 3.6.1)
 crayon        1.3.4   2017-09-16 [2] CRAN (R 3.6.1)
 DBI           1.0.0   2018-05-02 [2] CRAN (R 3.6.1)
 dbplyr        1.4.2   2019-06-17 [2] CRAN (R 3.6.1)
 desc          1.2.0   2018-05-01 [2] CRAN (R 3.6.1)
 devtools      2.2.1   2019-09-24 [2] CRAN (R 3.6.1)
 digest        0.6.23  2019-11-23 [2] CRAN (R 3.6.1)
 dplyr       * 0.8.3   2019-07-04 [2] CRAN (R 3.6.1)
 ellipsis      0.3.0   2019-09-20 [2] CRAN (R 3.6.1)
 evaluate      0.14    2019-05-28 [2] CRAN (R 3.6.1)
 farver        2.0.1   2019-11-13 [2] CRAN (R 3.6.1)
 forcats     * 0.4.0   2019-02-17 [2] CRAN (R 3.6.1)
 fs            1.3.1   2019-05-06 [2] CRAN (R 3.6.1)
 generics      0.0.2   2018-11-29 [2] CRAN (R 3.6.1)
 ggplot2     * 3.2.1   2019-08-10 [2] CRAN (R 3.6.1)
 ggridges      0.5.1   2018-09-27 [2] CRAN (R 3.6.1)
 ggsci       * 2.9     2018-05-14 [2] CRAN (R 3.6.1)
 glue          1.3.1   2019-03-12 [2] CRAN (R 3.6.1)
 gtable        0.3.0   2019-03-25 [2] CRAN (R 3.6.1)
 haven         2.2.0   2019-11-08 [2] CRAN (R 3.6.1)
 here        * 0.1     2017-05-28 [2] CRAN (R 3.6.1)
 hms           0.5.2   2019-10-30 [2] CRAN (R 3.6.1)
 htmltools     0.4.0   2019-10-04 [2] CRAN (R 3.6.1)
 httr          1.4.1   2019-08-05 [2] CRAN (R 3.6.1)
 jsonlite      1.6     2018-12-07 [2] CRAN (R 3.6.1)
 khroma      * 1.4.0   2020-10-05 [1] CRAN (R 3.6.1)
 knitr         1.26    2019-11-12 [2] CRAN (R 3.6.1)
 labeling      0.3     2014-08-23 [2] CRAN (R 3.6.1)
 lattice       0.20-38 2018-11-04 [2] CRAN (R 3.6.1)
 lazyeval      0.2.2   2019-03-15 [2] CRAN (R 3.6.1)
 lifecycle     0.1.0   2019-08-01 [2] CRAN (R 3.6.1)
 lubridate     1.7.4   2018-04-11 [2] CRAN (R 3.6.1)
 magrittr      1.5     2014-11-22 [2] CRAN (R 3.6.1)
 memoise       1.1.0   2017-04-21 [2] CRAN (R 3.6.1)
 modelr        0.1.5   2019-08-08 [2] CRAN (R 3.6.1)
 munsell       0.5.0   2018-06-12 [2] CRAN (R 3.6.1)
 nlme          3.1-142 2019-11-07 [2] CRAN (R 3.6.1)
 pillar        1.4.2   2019-06-29 [2] CRAN (R 3.6.1)
 pkgbuild      1.0.6   2019-10-09 [2] CRAN (R 3.6.1)
 pkgconfig     2.0.3   2019-09-22 [2] CRAN (R 3.6.1)
 pkgload       1.0.2   2018-10-29 [2] CRAN (R 3.6.1)
 plyr          1.8.4   2016-06-08 [2] CRAN (R 3.6.1)
 prettyunits   1.0.2   2015-07-13 [2] CRAN (R 3.6.1)
 processx      3.4.1   2019-07-18 [2] CRAN (R 3.6.1)
 ps            1.3.0   2018-12-21 [2] CRAN (R 3.6.1)
 purrr       * 0.3.3   2019-10-18 [2] CRAN (R 3.6.1)
 R6            2.4.1   2019-11-12 [2] CRAN (R 3.6.1)
 Rcpp          1.0.3   2019-11-08 [2] CRAN (R 3.6.1)
 readr       * 1.3.1   2018-12-21 [2] CRAN (R 3.6.1)
 readxl        1.3.1   2019-03-13 [2] CRAN (R 3.6.1)
 remotes       2.1.0   2019-06-24 [2] CRAN (R 3.6.1)
 reprex        0.3.0   2019-05-16 [2] CRAN (R 3.6.1)
 reshape2    * 1.4.3   2017-12-11 [2] CRAN (R 3.6.1)
 rlang         0.4.2   2019-11-23 [2] CRAN (R 3.6.1)
 rmarkdown     1.18    2019-11-27 [2] CRAN (R 3.6.1)
 rprojroot     1.3-2   2018-01-03 [2] CRAN (R 3.6.1)
 rstudioapi    0.10    2019-03-19 [2] CRAN (R 3.6.1)
 rvest         0.3.5   2019-11-08 [2] CRAN (R 3.6.1)
 scales        1.1.0   2019-11-18 [2] CRAN (R 3.6.1)
 sessioninfo   1.1.1   2018-11-05 [2] CRAN (R 3.6.1)
 stringi       1.4.3   2019-03-12 [2] CRAN (R 3.6.1)
 stringr     * 1.4.0   2019-02-10 [2] CRAN (R 3.6.1)
 testthat      2.3.0   2019-11-05 [2] CRAN (R 3.6.1)
 tibble      * 2.1.3   2019-06-06 [2] CRAN (R 3.6.1)
 tidyr       * 1.0.0   2019-09-11 [2] CRAN (R 3.6.1)
 tidyselect    0.2.5   2018-10-11 [2] CRAN (R 3.6.1)
 tidyverse   * 1.3.0   2019-11-21 [2] CRAN (R 3.6.1)
 usethis       1.5.1   2019-07-04 [2] CRAN (R 3.6.1)
 vctrs         0.2.0   2019-07-05 [2] CRAN (R 3.6.1)
 withr         2.1.2   2018-03-15 [2] CRAN (R 3.6.1)
 xfun          0.11    2019-11-12 [2] CRAN (R 3.6.1)
 xml2          1.2.2   2019-08-09 [2] CRAN (R 3.6.1)
 yaml          2.2.0   2018-07-25 [2] CRAN (R 3.6.1)
 zeallot       0.1.0   2018-01-28 [2] CRAN (R 3.6.1)

[1] /home/ad.abt.local/wchiu/R/library
[2] /opt/R/3.6.1/lib64/R/library
LS0tCnRpdGxlOiAiUEZIeFMgMSBjb21wYXJ0bWVudCBQbG90cyAodjgpIgphdXRob3I6ICJXZWloc3VlaCBDaGl1LCBDbGFpcmUgTGF5LCBQYXJrZXIgTWFsZWsiCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVGJylgIgprbml0OiAoZnVuY3Rpb24oaW5wdXRGaWxlLCBlbmNvZGluZykge291dGRpciA9IGZpbGUucGF0aChkaXJuYW1lKGlucHV0RmlsZSksICdtYXJrZG93bicsIHBhc3RlMChmb3JtYXQoU3lzLnRpbWUoKSwgJyVGJykpKTsgaWYoIWRpci5leGlzdHMob3V0ZGlyKSl7ZGlyLmNyZWF0ZShvdXRkaXIpfTsgcm1hcmtkb3duOjpyZW5kZXIoaW5wdXRGaWxlLCBlbmNvZGluZyA9IGVuY29kaW5nLCBvdXRwdXRfZm9ybWF0ID0gJ2FsbCcsIG91dHB1dF9kaXIgPSBvdXRkaXIpIH0pCm91dHB1dDoKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IGthYmxlCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1Ci0tLQoKYGBge3Igc2V0dXB9CmxpYnJhcnkoY29kYSkKbGlicmFyeShiYXllc3Bsb3QpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dzY2kpCmxpYnJhcnkoa2hyb21hKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZXNoYXBlMikKbGlicmFyeShoZXJlKQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGRwaSA9IDMwMCApCmBgYAoKU2V0IHVwIE1DU2ltIGZpbGUKCmBgYHtyIG1jc2ltfQojIHRoaXMgbWFya2Rvd24gZmlsZSBtdXN0IGJlIHNhdmVkIGluIHRvcCBsZXZlbCBkaXJlY3RvcnkgZm9yIHRoZSBmb2xsb3dpbmcgdG8gd29yazsgdGhlIG1jc2ltIGNvZGUgZGVwZW5kcyBvbiBnZXR3ZCByZXN1bHRzLgptZGlyIDwtICJNQ1NpbSIKc291cmNlKGhlcmU6OmhlcmUobWRpciwic2V0dXBfTUNTaW0uUiIpKQojIE1ha2UgbW9kLmV4ZSAodXNlZCB0byBjcmVhdGUgbWNzaW0gZXhlY3V0YWJsZSBmcm9tIG1vZGVsIGZpbGUpCm1ha2Vtb2QoKSAKYGBgCgojIyBTZXQgZmlsZW5hbWVzIGFuZCBsb2FkIGRhdGEKCgpgYGB7ciBNQ01DICBtb2RlbCBmaWxlLCBpbmNsdWRlPUZBTFNFfQpzZXQuc2VlZCgzMTQxNTkpCnNhIDwtICJDYmdkLTgwXyIgIyBBREQgc2Vuc2l0aXZpdHkgdGVzdCB0YWcgdG8gcGxvdCBmaWxlbmFtZXMKIyBNX2xuX0NiZ2Rfc2MgdG8gYmUgY2VudGVyZWQgb24gbG4oMC44KSBpbnN0ZWFkIG9mIDAgKGRlY3JlYXNlZCBieSAyMCUpCiMgTWFrZSBtb2RlbCBleGVjdXRhYmxlCm1vZGVsX2ZpbGU8LSAiUEZBU18xY3B0X3Y4LnBvcC5NQ01DLm1vZGVsLlIiCm1ha2VtY3NpbShtb2RlbF9maWxlKQoKaW5fZmlsZSA8LSAiUEZIeFNfMWNwdF92OC5Qb3BNQ01DX01lYW5JbmRpdlRyYWluVGVzdC5pbi5SIiAKcGZhc19uYW1lIDwtIGdzdWIoIl8xY3B0X3Y4LlBvcE1DTUNfTWVhbkluZGl2VHJhaW5UZXN0LmluLlIiLCAiIiwgaW5fZmlsZSkKCnNhbXBzIDwtIGRhdGEuZnJhbWUoKQpjaGVja3MgPC0gZGF0YS5mcmFtZSgpCnNhbXBzLmxpc3QgPC0gbGlzdCgpCmZvciAoY2hhaW5udW0gaW4gMTo0KSB7CiAgb25lY2hhaW4gPC0gcmVhZC5kZWxpbShzdWIoIi5pbi5SIixwYXN0ZTAoY2hhaW5udW0sIi5vdXQiKSxpbl9maWxlKSkKICBzYW1wcy5saXN0W1tjaGFpbm51bV1dPC1tY21jKG9uZWNoYWluW2Zsb29yKG5yb3cob25lY2hhaW4pIC8gMik6bnJvdyhvbmVjaGFpbiksIC0xXSkKICBzYW1wcyA8LSByYmluZChzYW1wcyxzYW1wcy5saXN0W1tjaGFpbm51bV1dKQogIG9uZWNoZWNrIDwtIHJlYWQuZGVsaW0oc3ViKCIuaW4uUiIscGFzdGUwKGNoYWlubnVtLCIuY2hlY2sub3V0IiksaW5fZmlsZSkpCiAgb25lY2hlY2skQ2hhaW4gPC0gY2hhaW5udW0KICBjaGVja3MgPC0gcmJpbmQoY2hlY2tzLG9uZWNoZWNrKQp9CnNhbXBzLm1jbWNsaXN0IDwtIGFzLm1jbWMubGlzdChzYW1wcy5saXN0KQoKbG9hZCgiUEZIeFNfMWNwdF92OF9tdWx0aWNoZWNrLlJkYXRhIikgCmBgYAoKIyMgU2V0IHVwIGRhdGFzZXQKCmBgYHtyIGRhdGFzZXQtTFVULCBjYWNoZSA9IFRSVUV9CmlkX2x1dCA8LSBtdWx0aWNoZWNrJGRmX2NoZWNrICU+JSBzZWxlY3QoTGV2ZWwpICU+JSB1bmlxdWUgKCkgICU+JQogIG11dGF0ZShkYXRhc2V0ID0gYyggCiAgICByZXAoIkRlY2F0dXIgTSBUcmFpbiIsIDkpLAogICAgcmVwKCJEZWNhdHVyIEYgVHJhaW4iLCA5KSwKICAgIHJlcCgiRGVjYXR1ciBNIFRlc3QiLCA5KSwKICAgIHJlcCgiRGVjYXR1ciBGIFRlc3QiLCAxMCksCiAgICAnUGF1bHNib3JvLVRyYWluJywnSG9yc2hhbS1UcmFpbicsCiAgICAnV2FybWluc3Rlci1UZXN0JywnV2FycmluZ3Rvbi1UcmFpbicpLCAKICAgIFNleCA9IGMoIAogICAgcmVwKCJNIiwgOSksCiAgICByZXAoIkYiLCA5KSwKICAgIHJlcCgiTSIsIDkpLAogICAgcmVwKCJGIiwgMTApLAogICAgJ01peGVkJywgJ01peGVkJywgICdNaXhlZCcsICdNaXhlZCcpLAogICAgQ2l0eSA9IGMoIAogICAgcmVwKCJEZWNhdHVyIiwgMTgpLAogICAgcmVwKCJEZWNhdHVyIiwgMTkpLAogICAgJ1BhdWxzYm9ybycsJ0hvcnNoYW0nLCdXYXJtaW5zdGVyJywnV2FycmluZ3RvbicpLCAKICAgIFRyYWluX1Rlc3QgPSBjKCAKICAgIHJlcCgiVHJhaW4iLCA5KSwKICAgIHJlcCgiVHJhaW4iLCA5KSwKICAgIHJlcCgiVGVzdCIsIDkpLAogICAgcmVwKCJUZXN0IiwgMTApLAogICAgJ1RyYWluJywgJ1RyYWluJywgJ1Rlc3QnLCAnVGVzdCcpLAogICAgZGF0YXR5cGUgPSBjKAogICAgICByZXAoIkluZGl2aWR1YWwiLDkrOSs5KzEwKSwKICAgICAgcmVwKCJTdW1tYXJ5Iiw0KSksCiAgICBTaW11bGF0aW9uID0gcm93X251bWJlcigpLAogICAgdmFyaWFibGUgPSBwYXN0ZTAoZGF0YXNldCwgIiAiLFNpbXVsYXRpb24pKQoKaWRfbHV0JGRhdGFzZXQgPC0gZmFjdG9yKGlkX2x1dCRkYXRhc2V0LGxldmVscz0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiRGVjYXR1ciBNIFRyYWluIiwiRGVjYXR1ciBGIFRyYWluIiwiQXJuc2JlcmcgTSBUcmFpbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFybnNiZXJnIEYgVHJhaW4iLCJEZWNhdHVyIE0gVGVzdCIsIkRlY2F0dXIgRiBUZXN0IiwiQXJuc2JlcmcgTSBUZXN0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXJuc2JlcmcgRiBUZXN0IiwiTWlubmVzb3RhIFRyYWluIiwiTWlubmVzb3RhIFRlc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdMdWJlY2stQmFydGVsbC1UcmFpbicsICdMdWJlY2stQmFydGVsbC1UZXN0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTGl0dGxlIEhvY2tpbmctQmFydGVsbC1UcmFpbicsICdMaXR0bGUgSG9ja2luZy1CYXJ0ZWxsLVRlc3QnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdMaXR0bGUgSG9ja2luZy1FbW1ldHQtVGVzdCcsJ1BhdWxzYm9yby1UcmFpbicsJ0hvcnNoYW0tVHJhaW4nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdXYXJtaW5zdGVyLVRlc3QnLCdXYXJyaW5ndG9uLVRyYWluJykpCmlkX2x1dCRDaXR5IDwtIGZhY3RvcihpZF9sdXQkQ2l0eSxsZXZlbHMgPSAKICAgICAgICAgICAgICAgICAgICAgICAgYygiRGVjYXR1ciIsIkFybnNiZXJnIiwiTWlubmVzb3RhIiwnTHViZWNrLUJhcnRlbGwnLAogICAgICAgICAgICAgICAgICAgICAgICAgICdMaXR0bGUgSG9ja2luZy1CYXJ0ZWxsJywnTGl0dGxlIEhvY2tpbmctRW1tZXR0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAnUGF1bHNib3JvJywnSG9yc2hhbScsJ1dhcm1pbnN0ZXInLCdXYXJyaW5ndG9uJykpCiAKCmluZGl2X2x1dCA8LSBpZF9sdXQgJT4lIAogIGZpbHRlcihDaXR5ICVpbiUgYygiRGVjYXR1ciIpKSAlPiUKICBtdXRhdGUoICBkYXRhc2V0ID0gYXMuZmFjdG9yKGRhdGFzZXQpKQoKbnYgPC0gZGF0YS5mcmFtZShkYXRhc2V0ID11bmlxdWUoaW5kaXZfbHV0JGRhdGFzZXQpLCAKICAgICAgICAgICB2YXJpYWJsZT0gcmVwKCJQb3AgR00iLCA0KSwKICAgICAgICAgICB0eXBlPSByZXAoIlBvcCBHTSIsIDQpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmBgYAoKCiMjIFNjYXR0ZXIgcGxvdCBvZiBwcmVkaWN0aW9ucyAobWVkaWFuIG9mIG11bHRpY2hlY2sgc2FtcGxlcykgdmVyc3VzIGRhdGEuCgpUaGlzIGlzIGEgRmlndXJlIDIgcGFuZWwuICBOZWVkZWQgdG8gdXNlICJzY2FsZT0xLjEiIGluIGdnc2F2ZSB0byBtYXRjaCBQRk9BLgoKYGBge3IgcHJlZGljdGlvbi12ZXJzdXMtZGF0YSAsIGNhY2hlID0gVFJVRSxmaWcuaGVpZ2h0PTMuNSxmaWcud2lkdGg9OCxkcGk9NjAwfQpucm93KG11bHRpY2hlY2skZGZfY2hlY2spCm5yb3coaWRfbHV0KQptdWx0aWNoZWNrJGRmX2NoZWNrICU+JSBsZWZ0X2pvaW4oaWRfbHV0KSAlPiUgbnJvdygpCgpuYW1lcyhtdWx0aWNoZWNrJGRmX2NoZWNrKQoKbXVsdGljaGVjazIgPC0gbXVsdGljaGVjayRkZl9jaGVjayAlPiUgCiAgbGVmdF9qb2luKGlkX2x1dCwgYnkgPSBjKCJMZXZlbCIsICJTaW11bGF0aW9uIikpJT4lIAogIGdyb3VwX2J5X2F0ICggdmFycygtUHJlZGljdGlvbikpICU+JSAKICBzdW1tYXJpc2UoUHJlZGljdGlvbiA9IG1lZGlhbihQcmVkaWN0aW9uKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KENpdHkpICU+JSAKICBtdXRhdGUoVHJhaW5fVGVzdCA9IGZhY3RvcihUcmFpbl9UZXN0LCBsZXZlbHMgPSBjKCJUcmFpbiIsICJUZXN0IikpLAogICAgICAgICBgQ2l0eSAoZGF0YXR5cGUpYCA9IGZhY3RvciAocGFzdGUwKENpdHksICJcbigiLCBkYXRhdHlwZSwgIilcbiIpICksCiAgICAgICAgIGxhYmVsID0gY2FzZV93aGVuKFRyYWluX1Rlc3Q9PSJUcmFpbiIgfiAiRzogUEZIeFMgVHJhaW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICBUcmFpbl9UZXN0PT0iVGVzdCIgIH4gIkg6IFBGSHhTIFRlc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKQogCiNkZWZpbmUgY29sb3IgZm9yIHRlc3RpbmcgYm94cGxvdHMKYnBfY29scyA8LSBjIChhcy5jaGFyYWN0ZXIgKGtocm9tYTo6Y29sb3VyKCJtdXRlZCIpKDkpKSAsICIjMTkxOTE5IikgICAKYnBfY29scyA8LWJwX2NvbHNbYygxLDcsMTA6OCldIyBwbG90X3NjaGVtZV9jb2xvdXJibGluZChicF9jb2xzKSAKCiMjIyBDcmVhdGUgYWVzdGhldGljcyBsb29rdXAKYWVzX2x1dCA8LSBtdWx0aWNoZWNrMiAlPiUgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShDaXR5LCBkYXRhdHlwZSwgIGBDaXR5IChkYXRhdHlwZSlgICkgJT4lIHN1bW1hcmlzZSAoKSAlPiUgdW5ncm91cCgpICU+JQogIG11dGF0ZSggY29scyA9IGJwX2NvbHMsIGNpdHlfZmlsbHMgPSAgIGJwX2NvbHMgLCAKICAgICAgICAgICMgZm9yIGluZGl2aWR1YWwgbGV2ZWwgb24gcG9pbnQgcGxvdCAobXVsdGljaGVjazIpLCBkYXJrZW4gb3V0bGluZXMgZm9yIHZpc2liaWxpdHksIHVzZSBzdGFuZGFyZCBjb2xvcnMgb3RoZXJ3aXNlCiAgICAgICAgIGNpdHlfb3V0bGluZXMgPSAgaWZfZWxzZShkYXRhdHlwZSA9PSAiSW5kaXZpZHVhbCIgICwgIGNvbG9yc3BhY2U6OmRhcmtlbihjaXR5X2ZpbGxzLCAwLjMpLCBjaXR5X2ZpbGxzKSAsICAKICAgICAgICAgc2hhcGVzID0gY2FzZV93aGVuKGRhdGF0eXBlID09ICJJbmRpdmlkdWFsIiAgJiBgQ2l0eWAgJWluJSBjKCdEZWNhdHVyJywgJ0FybnNiZXJnJywgJ01pbm5lc290YScpICAgfiAgMjMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhdHlwZSA9PSAiU3VtbWFyeSIgJmBDaXR5YCAlaW4lIGMoIkhvcnNoYW0iLCAiV2FybWluc3RlciIsICAiV2FycmluZ3RvbiIpIH4gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGF0eXBlID09ICJTdW1tYXJ5IiAmIGBDaXR5YCA9PSAiUGF1bHNib3JvIiB+IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gMTggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksIAogICAgICAgICBzaXplID0gaWZfZWxzZShkYXRhdHlwZSA9PSJJbmRpdmlkdWFsIiwgMS43NSwgMi41ICkgKSAgCgoKCnNvdXJjZSggcGFzdGUwKGdzdWIoYmFzZW5hbWUoaGVyZSgpKSwgJ3NoYXJlZF9mdW5jdGlvbnMnLCBoZXJlKCkpLCAnL3Bsb3Rfc2NhdHRlcl9tY2hlY2sucicpKQoKcDIgPC0gcGxvdF9zY2F0dGVyX21jaGVjayhkZnJhbWUgPSBtdWx0aWNoZWNrMiwgIHBmYXNfbm9tID0gcGZhc19uYW1lLCBhZXNfbHV0X2ZuID0gYWVzX2x1dCApCnByaW50KHAyKSAKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLCBwYXN0ZTAoIHNhLCJtdWx0aWNoZWNrcGxvdF8iLCBwZmFzX25hbWUsCiAgICAgICAgICAgICAgICIucGRmIikpLHAyLGRwaT02MDAsIHNjYWxlPTEuMSkKCmBgYAoKIyMgUGFyc2UgbXVsdGljaGVjawoKYGBge3IgZG8tbXVsdGljaGVjaywgY2FjaGUgPSBUUlVFLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0xOH0KCmRmX2NoZWNrIDwtIG11bHRpY2hlY2skZGZfY2hlY2sKZGZfY2hlY2sgPC0gc3Vic2V0KGRmX2NoZWNrLERhdGEgPiAwKSAKCm4xIDwtIG5yb3coZGZfY2hlY2spCmlkX2Noa3MgPC0gZGZfY2hlY2sgJT4lIHNlbGVjdChMZXZlbCkgJT4lIHVuaXF1ZSgpICU+JSBiaW5kX2NvbHMoaWRfbHV0KSAgJT4lCiAgbXV0YXRlKGRhdGFzZXQgPSBhcy5mYWN0b3IoZGF0YXNldCksIFNleCA9IGFzLmZhY3RvcihTZXgpLCBDaXR5ID0gYXMuZmFjdG9yKENpdHkpLCAKICAgICAgICAgVHJhaW5fVGVzdCA9IGFzLmZhY3RvcihUcmFpbl9UZXN0KSkKCmRmX2NoZWNrIDwtIGRmX2NoZWNrICU+JSBsZWZ0X2pvaW4oaWRfY2hrcyklPiUKICBtdXRhdGUoRGF0YXNldCA9IHBhc3RlKGFzLmNoYXJhY3RlcihkYXRhc2V0KSwgU2ltdWxhdGlvbiksCiAgICAgICAgIFNleCA9IG9yZGVyZWQoU2V4LCBsZXZlbHMgPSBjKCJNIiwgIkYiLCAiTWl4ZWQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTWFsZSIsICJGZW1hbGUiLCAiTWl4ZWQgKGFsbCBzZXhlcykiKSkpCm4yIDwtIG5yb3coZGZfY2hlY2spCmlmKG4xICE9IG4yKXByaW50KCJkdXBsaWNhdGVzIGNyZWF0ZWQgaW4gaWQtbHV0IGpvaW4iKQpgYGAKCgpgYGB7ciBkby1tdWx0aWNoZWNrLTIsIGNhY2hlID0gVFJVRSwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9MTh9CmRmX2NoZWNrJFRpbWUuZGVzYyA8LSBhcy5jaGFyYWN0ZXIocGFzdGUwKCJUPSIsZGZfY2hlY2skVGltZSkpCmRmX2NoZWNrJFRpbWUuZGVzY1tkZl9jaGVjayRUaW1lLmRlc2MgPT0gIlQ9MWUtMDYiXSA8LSAiU3RlYWR5U3RhdGUiCmRmX2NoZWNrJERhdGFzZXQuVGltZSA8LSBpbnRlcmFjdGlvbihkZl9jaGVjayREYXRhc2V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZfY2hlY2skVGltZS5kZXNjLGxleC5vcmRlcj1UUlVFKQpkZl9jaGVjayREYXRhc2V0LlRpbWUgPC0gZmFjdG9yKGRmX2NoZWNrJERhdGFzZXQuVGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9bGV2ZWxzKGRmX2NoZWNrJERhdGFzZXQuVGltZSkpCmNhbGliZGF0YSA8LSBkZl9jaGVja1ssbmFtZXMoZGZfY2hlY2spICE9ICJQcmVkaWN0aW9uIl0KY2FsaWJkYXRhIDwtIGNhbGliZGF0YVshZHVwbGljYXRlZChjYWxpYmRhdGEpLF0KcHJpbnQoY2FsaWJkYXRhKQogCiNNdWx0aWNoZWNrIHBsb3QKCiMgU3BsaXQgU3RlYWR5IFN0YXRlIEdyb3VwIGludG8gZGlmZmVyZW50IHBvcHVsYXRpb25zIGZvciBib3hwbG90IGdyb3VwaW5nCiNkZl9jaGVja1tkZl9jaGVjayRUaW1lLmRlc2MgPT0gIlN0ZWFkeVN0YXRlIiAmIGdyZXBsKCJMdWJlY2siLGRmX2NoZWNrJERhdGFzZXQpLF0kVGltZS5kZXNjIDwtICJMdWJlY2siCiNkZl9jaGVja1tkZl9jaGVjayRUaW1lLmRlc2MgPT0gIlN0ZWFkeVN0YXRlIiAmIGdyZXBsKCJMaXR0bGUgSG9ja2luZyIsZGZfY2hlY2skRGF0YXNldCksXSRUaW1lLmRlc2MgPC0gIkxpdHRsZSBIb2NraW5nIgpgYGAKTW9kaWZ5IGFlc3RoZXRpY3MgbG9va3VwIHRhYmxlIGZvciBib3hwbG90cyAKYGBge3IgbW9kLWFlcy1sdXR9CiMjICBhZGRpdGlvbmFsIHNvdXJjZSBhZXN0aGV0aWMgbG9va3VwIHRhYmxlIGZvciBncmV5LXNjYWxlIHRpbWUgKHllYXJzKTsgIG1lcmdlZCBsZWdlbmRzIHNhdmUgc3BhY2Ugb24gcGxvdHRpbmcgb3V0cHV0CnRpbWVzIDwtIGRmX2NoZWNrJT4lIHNlbGVjdChUaW1lLmRlc2MsIFRpbWUpICU+JSAgdW5pcXVlICgpICU+JSAKICBtdXRhdGUocmFuayA9IHJhbmsoVGltZSkgLCBncmV5ID0gZ3JleS5jb2xvcnMoc3RhcnQ9MSxlbmQ9MC40LCBuID0gbigpKSwKICAgICAgICAgYWxwaGEgPSAocmFuaykvOCkgJT4lIAogIHNlbGVjdCgtVGltZSkKIApkZl9jaGVjayA8LSBkZl9jaGVjayAlPiUgbXV0YXRlIChsZWdlbmRfbGFiZWwgPSAocGFzdGUwKENpdHksICJcbiIsIFRpbWUuZGVzYyApICkpICMgYWRkIGxlZ2VuZC1sYWJlbHMKYWVzX2x1dCA8LSBkZl9jaGVjayAlPiUgCiAgc2VsZWN0KENpdHksIFRyYWluX1Rlc3QsIGRhdGF0eXBlLFRpbWUsIFRpbWUuZGVzYywgbGVnZW5kX2xhYmVsKSAlPiUgdW5pcXVlICgpICU+JQogICBsZWZ0X2pvaW4oYWVzX2x1dFssIGMoIkNpdHkiLCAiY29scyIpXSwgYnkgPSAiQ2l0eSIpICU+JSB1bmdyb3VwICgpICU+JSB1bmlxdWUgKCklPiUKICAgbGVmdF9qb2luICh0aW1lcywgYnkgPSAiVGltZS5kZXNjIikgJT4lIAogICBhcnJhbmdlKGRhdGF0eXBlLCBDaXR5LCBUcmFpbl9UZXN0LCBUaW1lKSAgICAlPiUgCiAgIG11dGF0ZShhbHBoYSA9IGlmX2Vsc2UoQ2l0eSA9PSAiSG9yc2hhbSIsIGFscGhhLzIsIGFscGhhKSkgJT4lICMgb3RoZXJ3aXNlIHRvbyBkYXJrIHdpdGggdGhpcyBjb2xvcgogIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLmNoYXJhY3RlcikgCgpgYGAKCiMjIERlY2F0dXIgYm94cGxvdHMKCkNoYW5nZWQgZ3JleSBzdGFydCB0byAxIGluc3RlYWQgb2YgMC44LCBlbmQgYXQgMC42IGluc3RlYWQgb2YgMC40LgpDaGFuZ2VkIHNoYXBlIG9mIHN5bWJvbHMgc28gdGhleSBhcmUgZmlsbGVkLgoKYGBge3IgZG8tbXVsdGljaGVjay1kZWNhdHVyLCBjYWNoZSA9IFRSVUUsIGZpZy53aWR0aD02LjUsIGZpZy5oZWlnaHQ9My41LGRwaT02MDB9CiNHSAojIERlY2F0dXIgCgpkZl9kZWNhdCAgPC0gZGZfY2hlY2sgJT4lICAgCiAgZmlsdGVyKENpdHkgPT0gIkRlY2F0dXIiICYgVHJhaW5fVGVzdCAlaW4lIGMgKCJUcmFpbiIsICJUZXN0IikpICU+JSAKICBtdXRhdGUocGFuZWwgPSBvcmRlcmVkIChUcmFpbl9UZXN0LCBsZXZlbHMgPSBjICgiVHJhaW4iLCAiVGVzdCIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJHOiBQRkh4UyBEZWNhdHVyIFRyYWluIiwgIkg6IFBGSHhTIERlY2F0dXIgVGVzdCIpICkpCgphZXNfbHV0X2RmX2RmX2RlY2F0IDwtIGFlc19sdXQgJT4lIAogIGZpbHRlcihDaXR5ID09ICJEZWNhdHVyIiAmIFRyYWluX1Rlc3QgJWluJSBjICgiVHJhaW4iLCAiVGVzdCIpKSAlPiUgCiAgbXV0YXRlX2lmKGlzLmZhY3RvciwgYXMuY2hhcmFjdGVyKSAKCnNvdXJjZSggcGFzdGUwKGdzdWIoYmFzZW5hbWUoaGVyZSgpKSwgJ3NoYXJlZF9mdW5jdGlvbnMnLCBoZXJlKCkpLCAnL3Bsb3Rfc3VtX2JveHBsb3QucicpKQoKCnBsdF90cmFpbiA8LSBwbG90X3N1bV9ib3hwbG90ICAgKGRmcmFtZSA9IGRmX2RlY2F0LCBhZXNfbHV0PSBhZXNfbHV0X2RmX2RmX2RlY2F0LCBmYWNldHMgPSBUUlVFICwgcGZhc19ub20gPSBwZmFzX25hbWUgICAgICkgCnByaW50KHBsdF90cmFpbikKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsIkRlY2F0dXJUcmFpblRlc3Rib3hwbG90IixwZmFzX25hbWUsIi5wZGYiKSkscGx0X3RyYWluLGRwaT02MDApCiAgCmBgYAoKIyMgQWxsIGJveHBsb3RzCgpDaGFuZ2VkIGdyZXkgc3RhcnQgdG8gMSBpbnN0ZWFkIG9mIDAuOCwgZW5kIGF0IDAuNiBpbnN0ZWFkIG9mIDAuNC4KQWRkZWQgc2hhcGVzIGFuZCBmaWxscyB0byBkYXRhIHBvaW50cy4KCmBgYHtyIGRvLW11bHRpY2hlY2stYWxsLCBjYWNoZSA9IFRSVUUsIGZpZy53aWR0aD02LjUsIGZpZy5oZWlnaHQ9My41LGRwaT02MDB9CgpsZXRzIDwtIExFVFRFUlM7Cm5hbWVzKGxldHMpWzE6KGxlbmd0aCh1bmlxdWUoZGZfY2hlY2skZGF0YXNldCkpLTQpXTwtYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9jaGVjayRkYXRhc2V0KSlbNTpsZW5ndGgodW5pcXVlKGRmX2NoZWNrJGRhdGFzZXQpKV0KCmZvciAoZCBpbiB1bmlxdWUoZGZfY2hlY2skZGF0YXNldCkpIHsgIyBkID0gdW5pcXVlKGRmX2NoZWNrJGRhdGFzZXQpWzExXQogICAgZGRzZXQgPC0gZGZfY2hlY2sgJT4lICAgIAogICAgZmlsdGVyKGRhdGFzZXQgPT0gZCkgCiAgICAKICAgIGFlc19sdXRfZGRzZXQgPC0gZGRzZXQgJT4lIHNlbGVjdChsZWdlbmRfbGFiZWwsICBDaXR5LFRyYWluX1Rlc3QsZGF0YXR5cGUsIFRpbWUuZGVzYyAgKSAlPiUgdW5pcXVlICgpICU+JSBpbm5lcl9qb2luKGFlc19sdXQpCiAgICAgIAogICAgZ3QgPC0gaWZlbHNlKGlzLm5hKGxldHNbZF0pLGQscGFzdGUwKGxldHNbZF0sIjogIiwgZCkpCiAgICBwbHQgPC0gcGxvdF9zdW1fYm94cGxvdChkZnJhbWUgPSBkZHNldCwgYWVzX2x1dD0gYWVzX2x1dF9kZHNldCwgZ3RpdGxlPSBndCwgZmFjZXRzID0gRkFMU0UsIHBmYXNfbm9tID0gcGZhc19uYW1lKQogICAgIAogIHByaW50KHBsdCkKICBnZ3NhdmUoaGVyZSAoIm91dHB1dC1wbG90cyIsCiAgICAgICAgICAgICAgICBwYXN0ZTAoIHNhLCBkLCItYm94cGxvdC0iLCAKICAgICAgICAgICAgICAgIHBmYXNfbmFtZSwiLnBkZiIpKSAsCiAgICAgICAgIHBsdCxkcGk9NjAwKQoKfQoKIyMjIG1ha2UgVHJhaW5pbmcgcGxvdCAgCgpkZl9kX3RydCA8LSBkZl9jaGVjayAlPiUgICAKICAgICBmaWx0ZXIoIChUcmFpbl9UZXN0ID09ICJUcmFpbiIpICYgKChPdXRwdXRfVmFyID09ICJNX0NiZ2RfQ3NzIikgfCAoT3V0cHV0X1ZhciA9PSAiTV9Dc2VydW0iKSkpICU+JQogICAgIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLmNoYXJhY3RlcikgJT4lICAjIGRyb3AgZmFjdG9yIGxldmVscyB1bnVzZWQKICAgICBtdXRhdGUoRGF0YXNldC5UaW1lID0gZmFjdG9yKERhdGFzZXQuVGltZSkpIAogCgogYWVzX2x1dF9kZl9kX3RydCA8LSAgZGZfZF90cnQgJT4lIHNlbGVjdChDaXR5LCBkYXRhdHlwZSxUaW1lLCBUaW1lLmRlc2MsIGxlZ2VuZF9sYWJlbCkgJT4lIAogICBpbm5lcl9qb2luKGFlc19sdXQgICkgJT4lIAogICBzZWxlY3QoLVRyYWluX1Rlc3QpICU+JSB1bmdyb3VwICgpICU+JSB1bmlxdWUgKCkgIAoKcGx0X3RyYWluIDwtICAgIHBsb3Rfc3VtX2JveHBsb3QoZGZyYW1lID0gZGZfZF90cnQsIGFlc19sdXQ9IGFlc19sdXRfZGZfZF90cnQsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd0aXRsZT0iQTogU3VtbWFyeSBEYXRhIC0gVHJhaW4iICwgZmFjZXRzID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZmFzX25vbSA9IHBmYXNfbmFtZSApCiAgcHJpbnQocGx0X3RyYWluKQogIGdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIiwgcGFzdGUwKCBzYSwgIlN1bW1hcnlUcmFpbkRhdGFib3hwbG90IixwZmFzX25hbWUsIi5wZGYiKSksIHBsdF90cmFpbixkcGk9NjAwKQoKIyMjICBtYWtlIFRlc3QgcGxvdApkZl9kX3Rlc3QgPC0gZGZfY2hlY2sgJT4lICAgCiAgICBmaWx0ZXIoKFRyYWluX1Rlc3QgPT0gIlRlc3QiKSAmIAogICAgICAgICAgICAgKChPdXRwdXRfVmFyID09ICJNX0NiZ2RfQ3NzIikgfCAoT3V0cHV0X1ZhciA9PSAiTV9Dc2VydW0iKSkpICAlPiUKICAgICBtdXRhdGVfaWYoaXMuZmFjdG9yLCBhcy5jaGFyYWN0ZXIpICU+JSAgIyBkcm9wIGZhY3RvciBsZXZlbHMgdW51c2VkCiAgICAgbXV0YXRlKERhdGFzZXQuVGltZSA9IGZhY3RvcihEYXRhc2V0LlRpbWUpKSAKCmFlc19sdXRfZGZfZF90ZXN0IDwtICBkZl9kX3Rlc3QgJT4lIHNlbGVjdChDaXR5LCBkYXRhdHlwZSxUaW1lLCBUaW1lLmRlc2MsIGxlZ2VuZF9sYWJlbCkgJT4lIAogICBpbm5lcl9qb2luKGFlc19sdXQgICkgJT4lIAogICBzZWxlY3QoLVRyYWluX1Rlc3QpICU+JSB1bmdyb3VwICgpICU+JSB1bmlxdWUgKCkgIAoKcGx0X3Rlc3QgPC0gcGxvdF9zdW1fYm94cGxvdChkZnJhbWUgPSBkZl9kX3Rlc3QsIGFlc19sdXQ9IGFlc19sdXRfZGZfZF90ZXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndGl0bGU9IkI6IFN1bW1hcnkgRGF0YSAtIFRlc3QiLCBmYWNldHMgPSBGQUxTRSwgcGZhc19ub20gPSBwZmFzX25hbWUpCiAgcHJpbnQocGx0X3Rlc3QpCiAgZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsICJTdW1tYXJ5VGVzdERhdGFib3hwbG90IixwZmFzX25hbWUsIi5wZGYiKSksIHBsdF90ZXN0LGRwaT02MDApIApgYGAKCiMjIFBGSHhTCiMjIyBCYWNrZ3JvdW5kIHBvc3RlcmlvcnMKClNob3dzIHNoaWZ0IGluIGJhY2tncm91bmQgZXN0aW1hdGUuCgpgYGB7ciBnZXQgYmFja2dyb3VuZCwgY2FjaGUgPSBUUlVFLGZpZy5oZWlnaHQ9NixmaWcud2lkdGg9NSxkcGk9NjAwfQoKZ21zY2FsZTwtMC44CgpkYXQgPC0gbXVsdGljaGVjayRwYXJtcy5zYW1wWyxncmVwKCJNX2xuX0NiZ2QiLG5hbWVzKG11bHRpY2hlY2skcGFybXMuc2FtcCkpXQpkYXRhc2V0bmFtZXMgPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShjYWxpYmRhdGEkZGF0YXNldCkpCmRhdGFzZXRuYW1lcyA8LSBnc3ViKCIgVHJhaW4iLCItVHJhaW4iLGRhdGFzZXRuYW1lcykKZGF0YXNldG5hbWVzIDwtIGdzdWIoIiBUZXN0IiwiLVRyYWluIixkYXRhc2V0bmFtZXMpCmRhdGFzZXRuYW1lcyA8LSBnc3ViKCIgTSIsIiIsZGF0YXNldG5hbWVzKQpkYXRhc2V0bmFtZXMgPC0gZ3N1YigiIEYiLCIiLGRhdGFzZXRuYW1lcykKZGF0YXNldG5hbWVzPC1kYXRhc2V0bmFtZXNbIWR1cGxpY2F0ZWQoZGF0YXNldG5hbWVzKV0KZGF0YXNldG5hbWVzIDwtIGRhdGFzZXRuYW1lc1tncmVwKCJUcmFpbiIsZGF0YXNldG5hbWVzKV0KbmFtZXMoZGF0KSA8LSBkYXRhc2V0bmFtZXMKZGF0IDwtIGRhdFssZ3JlcCgiVHJhaW4iLG5hbWVzKGRhdCkpXQpkYXQuZGYgPC0gcGl2b3RfbG9uZ2VyKGRhdCwxOm5jb2woZGF0KSkKZGF0LmRmIDwtIHJiaW5kKGRhdC5kZiwKICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUobmFtZT0iUHJpb3IiLHZhbHVlPXJub3JtKDUwMDAsbT1sb2coZ21zY2FsZSksc2Q9MC40MDU1KSkpCmRhdC5kZiRuYW1lIDwtIGZhY3RvcihkYXQuZGYkbmFtZSxsZXZlbHM9cmV2KAogICAgICAgICAgICAgICAgICAgICAgICBjKCJQcmlvciIsZGF0YXNldG5hbWVzW2dyZXAoIlRyYWluIixkYXRhc2V0bmFtZXMpXSkpKQpkYXQuZGYkdmFsdWUgPC0gZXhwKGRhdC5kZiR2YWx1ZSkKCnA8LWdncGxvdChkYXQuZGYpKwogIyBnZW9tX3Zpb2xpbihhZXMoeD1uYW1lLHk9dmFsdWUsZmlsbD1uYW1lPT0iUHJpb3IiKSkrCiAgZ2VvbV9ib3hwbG90KGFlcyh4PW5hbWUseT12YWx1ZSxmaWxsPW5hbWU9PSJQcmlvciIpLG91dGxpZXIuc2hhcGU9TkEpKwogIHNjYWxlX3lfbG9nMTAoKStjb29yZF9mbGlwKCkrCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT1OVUxMLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YygiIzAwOTk4OCIsICIjRUU3NzMzIiApKSArCiAgdGhlbWVfY2xhc3NpYygpICsgIAogIHRoZW1lKGF4aXMudGl0bGUueS5sZWZ0ID0gZWxlbWVudF9ibGFuaygpKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBnbXNjYWxlLCBjb2xvcj0iZGFya2dyZXkiLCBsaW5ldHlwZSA9IDIsIHNpemUgPSAxLjI1KSsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yPSJibGFjayIsc2l6ZT0xKSkrCiAgeWxhYigiUG9zdGVyaW9yIHNoaWZ0IGluIEJhY2tncm91bmQgQ29uY2VudHJhdGlvbiIpCgpwcmludChwKQpnZ3NhdmUoaGVyZSAoIm91dHB1dC1wbG90cyIscGFzdGUwKCBzYSwgIlBGSHhTX0dNX0NiZ2QucGRmIikpICxwLGRwaT02MDApCgpgYGAKCiMjIyBIYWxmLWxpZmUKCkZvciBQRkh4UywgdGhlIHBvcHVsYXRpb24gR00gb2YgdGhlIGhhbGYtbGlmZSBoYXMgYSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIHRoYXQgaXMgbmFycm93ZXIgdGhhbiB0aGUgcHJpb3IsIHdpdGggYSBwb3N0ZXJpb3IgbWVkaWFuICg5NSUgQ0kpIGVzdGltYXRlIG9mIDMuMDYgKDIuMTYtNC4zNykgeWVhcnMuIFRoZSBwb3B1bGF0aW9uIEdTRCBwb3N0ZXJpb3IgaXMgbGFyZ2VyIHRoYW4gdGhlIHByaW9yIGF0IDEuNDcoMS40NC0xLjc1KS4KCmBgYHtyIHBvc3RlcmlvciBoaXN0b2dyYW1zLCBjYWNoZSA9IFRSVUV9CgoKZGF0IDwtIG11bHRpY2hlY2skcGFybXMuc2FtcFssYygiTV9sbl9rLjEuIiwiVl9sbl9rLjEuIiwgIk1fbG5fVmQuMS4iLCAiU0RfbG5fVmQuMS4iKV0KbmFtZXMoZGF0KSA8LSBjKCJNX2xuX2soMSkiLCJWX2xuX2soMSkiLCAiTV9sbl9WZCgxKSIsICJTRF9sbl9WZCgxKSIpCiAgCnNldC5zZWVkKDMuMTQxNTkpCmRhdCR6X2xuX2sgPC0gcm5vcm0obnJvdyhkYXQpKQpkYXQkel9sbl9WZCA8LSBybm9ybShucm93KGRhdCkpCmRhdCAlPiUgcmVuYW1lXygpCmRhdCRsbl9rX2kgPC0gZGF0JGBNX2xuX2soMSlgICsgc3FydChkYXQkYFZfbG5faygxKWApKmRhdCR6X2xuX2sKZGF0JGxuX1ZkX2kgPC0gZGF0JGBNX2xuX1ZkKDEpYCsgZGF0JGBTRF9sbl9WZCgxKWAqZGF0JHpfbG5fVmQKbGlubW9kIDwtIGxtKGxuX1ZkX2kgfiBsbl9rX2ksZGF0YT1kYXQpCmdncGxvdChkYXQpICsgZ2VvbV9wb2ludChhZXMobG5fa19pLGxuX1ZkX2kpKSArIAogIGxhYnMoc3VidGl0bGU9cGFzdGUoIkFkaiBSMiA9IixzaWduaWYoc3VtbWFyeShsaW5tb2QpJGFkai5yLnNxdWFyZWQsMikpKQpgYGAKCgojIyBDaGVjayBub3JtYWxpdHkKCmBgYHtyIG5vcm1hbGl0eSwgY2FjaGUgPSBUUlVFfQoKcXFub3JtKGRhdCRsbl9rX2ksbWFpbj0ibG4gayBRLVEgTm9ybWFsIikKcXFsaW5lKGRhdCRsbl9rX2ksY29sPSJyZWQiKQpwbG90KGVjZGYoZGF0JGxuX2tfaSkpCnggPC0gc2VxKC0zLDEsMC4wMSkKbV9sbl9rX2kgPC0gICBtZWFuKGRhdCRsbl9rX2kpCnNkX2xuX2tfaSA8LSBzZChkYXQkbG5fa19pKQpsaW5lcyh4LHBub3JtKHgsbWVhbj1tX2xuX2tfaSxzZD1zZF9sbl9rX2kpLGNvbD0icmVkIikKdGV4dChtX2xuX2tfaS0yKnNkX2xuX2tfaSwwLjkscGFzdGUoIm0gPSIsc2lnbmlmKG1fbG5fa19pLDQpLCJcbnNkID0iLHNpZ25pZihzZF9sbl9rX2ksNCkpKQoKcXFub3JtKGRhdCRsbl9WZF9pLG1haW49ImxuIFZkIFEtUSBOb3JtYWwiKQpxcWxpbmUoZGF0JGxuX1ZkX2ksY29sPSJyZWQiKQpwbG90KGVjZGYoZGF0JGxuX1ZkX2kpKQp4IDwtIHNlcSgtMywxLDAuMDEpCm1fbG5fVmRfaSA8LSBtZWFuKGRhdCRsbl9WZF9pKQpzZF9sbl9WZF9pIDwtIHNkKGRhdCRsbl9WZF9pKQoKbGluZXMoeCxwbm9ybSh4LG1lYW49bV9sbl9WZF9pLHNkPXNkX2xuX1ZkX2kpLGNvbD0icmVkIikKdGV4dChtX2xuX1ZkX2ktMipzZF9sbl9WZF9pLDAuOSxwYXN0ZSgibSA9IixzaWduaWYobV9sbl9WZF9pLDQpLCJcbnNkID0iLHNpZ25pZihzZF9sbl9WZF9pLDQpKSkKCmBgYAoKIyMgQ2FsY3VsYXRlIHRhYmxlIHZhbHVlcyBmb3IgaW5kaXZpZHVhbC1sZXZlbApgYGB7ciBtYWtlLWluZGl2aWR1YWwtcGFyYW0tb3V0LCBjYWNoZSA9IFRSVUV9CmhsX2kgPC0gbG9nKDIpLyBleHAoZGF0JGxuX2tfaSkgIyBpbmRpdmlkdWFsIGhhbGYtbGlmZSAKbWVkX2hsX2kgPC0gcGFzdGUoc2lnbmlmIChtZWRpYW4gKGhsX2kpLCAzKSkgIyBtZWRpYW4gb2YgaW5kaXZpZHVhbCBoYWxmLWxpZmUKY2lfbWVkX2hsX2kgPC0gICBwYXN0ZShzaWduaWYgKHF1YW50aWxlKGhsX2ksIHByb2I9YygwLjAyNSwwLjk3NSkpLCAzKSxjb2xsYXBzZT0iLSIpICMgOTVjaSBtZWQgaW5kaXZpZHVhbCBoYWxmbGlmZQpjaTk4X21lZF9obF9pIDwtICAgcGFzdGUoc2lnbmlmIChxdWFudGlsZShobF9pLCBwcm9iPWMoMC4wMSwwLjk5KSksIDMpLGNvbGxhcHNlPSItIikgIyA5OGNpIG1lZCBpbmRpdmlkdWFsIGhhbGZsaWZlCmdtX2hsX2kgPC0gcGFzdGUoc2lnbmlmIChleHAobWVhbihsb2coaGxfaSkpKSwgMykpICMgZ20gKHdoaWNoIHNob3VsZCBiZSByZWFsbHkgY2xvc2UpCmdzZF9obF9pIDwtIHBhc3RlKHNpZ25pZiAoZXhwKHNkKGxvZyhobF9pKSkpLCAzKSkgIyBnc2QgaW5kaXZpZHVhbAoKbWVkX1ZkX2kgPC0gcGFzdGUoc2lnbmlmIChtZWRpYW4oZXhwKGRhdCRsbl9WZF9pKSksIDMpKSAjIG1lZGlhbiBpbmRpdmlkdWFsIFZkCmNpX21lZF9WZF9pIDwtcGFzdGUoc2lnbmlmIChxdWFudGlsZShleHAoZGF0JGxuX1ZkX2kpLCBwcm9iPWMoMC4wMjUsMC45NzUpKSwgMyksY29sbGFwc2U9Ii0iKSAjIDk1Y2kgbWVkIGluZGl2aWR1YWwgVmQKY2k5OF9tZWRfVmRfaSA8LXBhc3RlKHNpZ25pZiAocXVhbnRpbGUoZXhwKGRhdCRsbl9WZF9pKSwgcHJvYj1jKDAuMDEsMC45OSkpLCAzKSxjb2xsYXBzZT0iLSIpICMgOThjaSBtZWQgaW5kaXZpZHVhbCBWZApnbV92ZF9pIDwtIHBhc3RlKHNpZ25pZiAoZXhwKG1lYW4oZGF0JGxuX1ZkX2kpKSwgMykpICMgZ20gKHdoaWNoIHNob3VsZCBiZSByZWFsbHkgY2xvc2UpCmdzZF92ZF9pPC0gcGFzdGUoc2lnbmlmIChleHAoc2QoZGF0JGxuX1ZkX2kpKSwgMykpICMgZ3NkIGluZGl2CmBgYAoKCmBgYHtyIGhhbGYtbGlmZSxmaWcuaGVpZ2h0PTIuNSxmaWcud2lkdGg9NCxkcGk9NjAwfQpQRkh4U19wcmlvcnMgPC0gZGF0YS5mcmFtZSgKICBoYWxmbGlmZV9HTT0gbG9nKDIpL3Jsbm9ybSg1MDAwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFubG9nPS0yLjAzNDIyLHNkbG9nPTAuNDA1NSkpCk1fayA8LSBleHAoYXMubnVtZXJpYyhkYXQkYE1fbG5faygxKWApKQpQRkh4U19oYWxmbGlmZV9HTSA8LSBsb2coMikvTV9rCgpQRkh4U19obGdtX3ByX21lZCA8LSBzaWduaWYobWVkaWFuKFBGSHhTX3ByaW9ycyRoYWxmbGlmZV9HTSwzKSkKUEZIeFNfaGxnbV9wcl9tZWRfOTVjaSA8LXBhc3RlKHNpZ25pZihxdWFudGlsZShQRkh4U19wcmlvcnMkaGFsZmxpZmVfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZT0iLSIpCgpQRkh4U19obF9tZWRpYW5fZ20gPC0gc2lnbmlmKG1lZGlhbihQRkh4U19oYWxmbGlmZV9HTSksMykKUEZIeFNfaGxfbWVkaWFuX2dtXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGSHhTX2hhbGZsaWZlX0dNLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2I9YygwLjAyNSwwLjk3NSkpLDMpLGNvbGxhcHNlPSItIikKCnA8LWdncGxvdCgpKwogIHN0YXRfZGVuc2l0eShhZXMoaGFsZmxpZmVfR00sIGNvbG9yID0gIlByaW9yIiksZGF0YT1QRkh4U19wcmlvcnMsZ2VvbT0ibGluZSIsc2l6ZT0yKSsKICBzdGF0X2RlbnNpdHkoYWVzKFBGSHhTX2hhbGZsaWZlX0dNLCBzdGF0KGRlbnNpdHkpLGNvbG9yPSJQb3N0ZXJpb3IiKSxnZW9tPSJsaW5lIixzaXplPTEuNSApKwogIHhsaW0oMCwxNSkrCiAgbGFicyh0aXRsZSA9IGJxdW90ZSgiRzogUEZIeFMiflRbMS8yXX4iUG9wdWxhdGlvbiBHTSIpICAsCiAgICAgICBzdWJ0aXRsZT1wYXN0ZSgiUG9zdGVyaW9yIE1lZGlhbiAoOTUlIENJKTogIiwKICAgICAgICAgICAgICAgICAgICAgIFBGSHhTX2hsX21lZGlhbl9nbSwiICgiLAogICAgICAgICAgICAgICAgICAgICAgUEZIeFNfaGxfbWVkaWFuX2dtXzk1Y2ksCiAgICAgICAgICAgICAgICAgICAgICAiKSIsc2VwPSIiKSkrCiAgeGxhYihicXVvdGUoIlBvcHVsYXRpb24gR00iflRbMS8yXX4iKHlycykiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPU5VTEwsIwogICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKFByaW9yPSIjMDA5OTg4IiwgUG9zdGVyaW9yPSIjRUU3NzMzIiApKSArIAogIHRoZW1lX2NsYXNzaWMoKSArICAKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPWMoMC44LDAuNyksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG9yPU5BKSkKcHJpbnQocCkKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsICJQRkh4U19obF9nbS5wZGYiKSkscCxkcGk9NjAwKQogCmBgYAoKCgpgYGB7ciBQRkh4Uy1oYWxmLWxpZmUtZ3NkLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGZpZy5oZWlnaHQ9Mi41LGZpZy53aWR0aD00LGRwaT02MDB9ClBGSHhTX3ByaW9ycyRoYWxmbGlmZV9HU0QgPSAgZXhwKHNxcnQoZXhwKHJub3JtKDUwMDAwLG09bG9nKDAuMiksc2Q9bG9nKDEuMjc1KSkpKSkgClBGSHhTX2hhbGZsaWZlX0dTRCA8LSBleHAoc3FydChkYXQkYFZfbG5faygxKWApKQoKUEZIeFNfaGxnc2RfcHJfbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZIeFNfcHJpb3JzJGhhbGZsaWZlX0dTRCwzKSkKUEZIeFNfaGxnc2RfcHJfbWVkXzk1Y2kgPC1wYXN0ZShzaWduaWYocXVhbnRpbGUoUEZIeFNfcHJpb3JzJGhhbGZsaWZlX0dTRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9iPWMoMC4wMjUsMC45NzUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlPSItIikKUEZIeFNfaGxfZ3NkX21lZCA8LSBzaWduaWYobWVkaWFuKFBGSHhTX2hhbGZsaWZlX0dTRCksMykKUEZIeFNfaGxfZ3NkX21lZF85NWNpIDwtIHBhc3RlKHNpZ25pZihxdWFudGlsZShQRkh4U19oYWxmbGlmZV9HU0QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksMyksY29sbGFwc2U9Ii0iKQpwPC1nZ3Bsb3QoKSsKICBzdGF0X2RlbnNpdHkoYWVzKGhhbGZsaWZlX0dTRCwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGSHhTX3ByaW9ycyxnZW9tPSJsaW5lIiwgc2l6ZT0yKSsKICBzdGF0X2RlbnNpdHkoYWVzKFBGSHhTX2hhbGZsaWZlX0dTRCxzdGF0KGRlbnNpdHkpLCBjb2xvciA9ICJQb3N0ZXJpb3IiKSxnZW9tPSJsaW5lIixzaXplPTEuNSkrCiAgeGxpbSgxLDMpKwogIGxhYnModGl0bGUgPSBicXVvdGUoIkg6IFBGSHhTIn5UWzEvMl1+IlBvcHVsYXRpb24gR1NEIiksICAKICAgICAgIHN1YnRpdGxlPXBhc3RlKCJQb3N0ZXJpb3IgTWVkaWFuICg5NSUgQ0kpOiAiLAogICAgICAgICAgICAgICAgICAgICAgUEZIeFNfaGxfZ3NkX21lZCwiICgiLAogICAgICAgICAgICAgICAgICAgICAgUEZIeFNfaGxfZ3NkX21lZF85NWNpLAogICAgICAgICAgICAgICAgICAgICAgIikiLHNlcD0iIikpKwogIHhsYWIoYnF1b3RlKCJQb3B1bGF0aW9uIEdTRCJ+VFsxLzJdKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9TlVMTCwjCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzPWMoUHJpb3I9IiMwMDk5ODgiLCBQb3N0ZXJpb3I9IiNFRTc3MzMiICkpICsgCiAgIHRoZW1lX2NsYXNzaWMoKSArICAKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPWMoMC44LDAuNyksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG9yPU5BKSkKcHJpbnQocCkKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsICJQRkh4U19obF9nc2QucGRmIikpICxwLGRwaT02MDApCgpgYGAKCgojIyMgVm9sdW1lIG9mIGRpc3RyaWJ1dGlvbgpGb3IgUEZIeFMsIHRoZSBkYXRhIHdlcmUgbm90IHBhcnRpY3VsYXJseSBpbmZvcm1hdGl2ZSwgYnV0IHNsaWdodGx5IGluY3JlYXNlZCB0aGUgZXN0aW1hdGUgb2YgdGhlIG1lZGlhbiB0byAwLjMwOCgwLjIyMy0wLjU0OCkgc2xpZ2h0bHkgY29tcGFyZWQgdG8gdGhlIGNhc2Ugd2hlcmUgQ2JnZCB3YXMgY29uc2lkZXJlZCB0byBiZSBlbnRpcmVseSBmcm9tIG5vbi1kcmlua2luZyB3YXRlciBzb3VyY2VzLiBUaGV5IHdlcmUgbm90IGluZm9ybWF0aXZlIGFzIHRvIHRoZSBwb3B1bGF0aW9uIEdTRCwgd2l0aCB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgZXNzZW50aWFsbHkgdW5jaGFuZ2VkIGZyb20gdGhlIHByaW9ycy4KYGBge3IgUEZIeFMtdmQtZ20sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsZmlnLmhlaWdodD0yLjUsZmlnLndpZHRoPTQsZHBpPTYwMH0KUEZIeFNfcHJpb3JzJFZkX0dNIDwtIHJsbm9ybSg1MDAwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFubG9nPS0xLjM4NjI5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkbG9nPTAuMjYyNCkKUEZIeFNfVmRfR00gPC0gZXhwKGRhdCRgTV9sbl9WZCgxKWApCgogCgpQRkh4U192ZF9nbV9wcl9tZWQgPC0gc2lnbmlmKG1lZGlhbihQRkh4U19wcmlvcnMkVmRfR00sMykpClBGSHhTX3ZkX2dtX3ByX21lZF85NWNpIDwtIHBhc3RlKHNpZ25pZihxdWFudGlsZShQRkh4U19wcmlvcnMkVmRfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksIDMpLCBjb2xsYXBzZT0iLSIpClBGSHhTX3ZkX2dtX21lZCA8LSBzaWduaWYobWVkaWFuKFBGSHhTX1ZkX0dNKSwzKQpQRkh4U192ZF9nbV9tZWRfOTVjaSA8LSBwYXN0ZShzaWduaWYocXVhbnRpbGUoUEZIeFNfVmRfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksMyksY29sbGFwc2U9Ii0iKQoKcDwtZ2dwbG90KCkrCiAgc3RhdF9kZW5zaXR5KGFlcyhWZF9HTSwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGSHhTX3ByaW9ycyxnZW9tPSJsaW5lIixzaXplPTIpKwogIHN0YXRfZGVuc2l0eShhZXMoUEZIeFNfVmRfR00sc3RhdChkZW5zaXR5KSwgY29sb3IgPSAiUG9zdGVyaW9yIiksZ2VvbT0ibGluZSIsc2l6ZT0xLjUpKwogIHhsaW0oMCwxKStsYWJzKHRpdGxlID0gYnF1b3RlKCJHOiBQRkh4UyJ+VltkXX4iUG9wdWxhdGlvbiBHTSIpLAogICAgICAgICAgICAgICAgIHN1YnRpdGxlPXBhc3RlKCJQb3N0ZXJpb3IgTWVkaWFuICg5NSUgQ0kpOiAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBGSHhTX3ZkX2dtX21lZCwiICgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQRkh4U192ZF9nbV9tZWRfOTVjaSwiKSIsc2VwPSIiKSkrCiAgIHhsYWIoYnF1b3RlKCJQb3B1bGF0aW9uIEdNIn5WW2RdfiIobC9rZykiKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9TlVMTCwjCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzPWMoUHJpb3I9IiMwMDk5ODgiLCBQb3N0ZXJpb3I9IiNFRTc3MzMiICkpICsgIAogIHRoZW1lX2NsYXNzaWMoKSArICAKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPWMoMC44LDAuNyksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG9yPU5BKSkKcHJpbnQocCkKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsICJQRkh4U192ZF9nbS5wZGYiKSkgLHAsZHBpPTYwMCkKCmBgYAoKCmBgYHtyIFBGSHhTLXZkLXNkLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGZpZy5oZWlnaHQ9Mi41LGZpZy53aWR0aD00LGRwaT02MDB9ClBGSHhTX3ByaW9ycyRWZF9HU0QgPSBleHAoYWJzKHJub3JtKDUwMDAwLHNkPTAuMTcpKSkKUEZIeFNfVmRfR1NEIDwtIGV4cChkYXQkYFNEX2xuX1ZkKDEpYCkKClBGSHhTX3ZkX2dzZF9wcl9tZWQgPC0gc2lnbmlmKG1lZGlhbihQRkh4U19wcmlvcnMkVmRfR1NELDMpKQpQRkh4U192ZF9nc2RfcHJfbWVkXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGSHhTX3ByaW9ycyRWZF9HU0QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksIDMpLCBjb2xsYXBzZT0iLSIpCgpQRkh4U192ZF9nc2RfbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZIeFNfVmRfR1NEKSwzKQpQRkh4U192ZF9nc2RfbWVkXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGSHhTX1ZkX0dTRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9iPWMoMC4wMjUsMC45NzUpKSwzKSxjb2xsYXBzZT0iLSIpCgpwPC1nZ3Bsb3QoKSsKICBzdGF0X2RlbnNpdHkoYWVzKFZkX0dTRCwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGSHhTX3ByaW9ycyxnZW9tPSJsaW5lIixzaXplPTIpKwogIHN0YXRfZGVuc2l0eShhZXMoUEZIeFNfVmRfR1NELHN0YXQoZGVuc2l0eSksIGNvbG9yID0gIlBvc3RlcmlvciIpLGdlb209ImxpbmUiLHNpemU9MS41KSsKICB4bGltKDEsMykrCiAgbGFicyh0aXRsZSA9IGJxdW90ZSgiSDogUEZIeFMiflZbZF1+IlBvcHVsYXRpb24gR1NEICIpLAogICAgICAgc3VidGl0bGU9cGFzdGUoIlBvc3RlcmlvciBNZWRpYW4gKDk1JSBDSSk6ICIsCiAgICAgICAgICAgICAgICAgICAgICBQRkh4U192ZF9nc2RfbWVkLCIgKCIsCiAgICAgICAgICAgICAgICAgICAgICBQRkh4U192ZF9nc2RfbWVkXzk1Y2ksCiAgICAgICAgICAgICAgICAgICAgICAiKSIsc2VwPSIiKSkrCiAgeGxhYihicXVvdGUoIlBvcHVsYXRpb24gR1NEIn5WW2RdKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9TlVMTCwgCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKFByaW9yPSIjMDA5OTg4IiwgUG9zdGVyaW9yPSIjRUU3NzMzIiApKSArIAogIHRoZW1lX2NsYXNzaWMoKSArICAKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPWMoMC44LDAuNyksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG9yPU5BKSkKcHJpbnQocCkKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsIlBGSHhTX3ZkX2dzZC5wZGYiKSkgLHAsZHBpPTYwMCkKCmBgYAojIyMgQ2xlYXJhbmNlIChqdXN0IHBvcCBHTSkKCkNsIGlzIGsgKiBWZAoKYGBge3IgUEZIeFMtY2wtZ20sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsZmlnLmhlaWdodD0yLjUsZmlnLndpZHRoPTQsZHBpPTYwMH0KUEZIeFNfcHJpb3JzJENMX0dNIDwtIFBGSHhTX3ByaW9ycyRWZF9HTSAqIChsb2coMikvUEZIeFNfcHJpb3JzJGhhbGZsaWZlX0dNKQpQRkh4U19DTF9HTSA8LSBleHAoZGF0JGBNX2xuX1ZkKDEpYCArIGRhdCRgTV9sbl9rKDEpYCkKClBGSHhTX2NsX2dtX3ByX21lZCA8LSBzaWduaWYobWVkaWFuKFBGSHhTX3ByaW9ycyRDTF9HTSwzKSkKUEZIeFNfY2xfZ21fcHJfbWVkXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGSHhTX3ByaW9ycyRDTF9HTSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9iPWMoMC4wMjUsMC45NzUpKSwgMyksIGNvbGxhcHNlPSItIikKUEZIeFNfY2xfZ21fbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZIeFNfQ0xfR00pLDMpClBGSHhTX2NsX2dtX21lZF85NWNpIDwtIHBhc3RlKHNpZ25pZihxdWFudGlsZShQRkh4U19DTF9HTSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9iPWMoMC4wMjUsMC45NzUpKSwzKSxjb2xsYXBzZT0iLSIpCgpwPC1nZ3Bsb3QoKSsKICBzdGF0X2RlbnNpdHkoYWVzKENMX0dNLCBjb2xvciA9ICJQcmlvciIpLGRhdGE9UEZIeFNfcHJpb3JzLGdlb209ImxpbmUiLHNpemU9MikrCiAgc3RhdF9kZW5zaXR5KGFlcyhQRkh4U19DTF9HTSxzdGF0KGRlbnNpdHkpLCBjb2xvciA9ICJQb3N0ZXJpb3IiKSxnZW9tPSJsaW5lIixzaXplPTEuNSkrCiAgeGxpbSgwLDAuMjUpK2xhYnModGl0bGUgPSAiRDogUEZIeFMgQ2xlYXJhbmNlIFBvcC4gR00gIixzdWJ0aXRsZT1wYXN0ZSgiUG9zdGVyaW9yIE1lZGlhbiAoOTUlIENJKTogIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQRkh4U19jbF9nbV9tZWQsIiAoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQRkh4U19jbF9nbV9tZWRfOTVjaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiKSIsc2VwPSIiKSkrCiAgeGxhYigiUG9wLiBHTSBDTCAobC8oa2cteXIpKSIpKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPU5VTEwsIwogICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKFByaW9yPSIjMDA5OTg4IiwgUG9zdGVyaW9yPSIjRUU3NzMzIiApKSArICAKICB0aGVtZV9jbGFzc2ljKCkgKyAgCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbj1jKDAuOCwwLjcpLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yPSJibGFjayIsc2l6ZT0xKSwKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvcj1OQSkpCnByaW50KHApCmdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIixwYXN0ZTAoIHNhLCAiUEZIeFNfQ0xfZ20ucGRmIikpLCBwLGRwaT02MDApCgpgYGAKCgojIyBUYWJsZSBzaWduaWZpY2FudCBkaWdpdCB2YWx1ZXMKCmBgYHtyIHRhYmxlLXZhcnMgfQpQRkh4U19obGdtX3ByX21lZCA8LSBwYXN0ZShzaWduaWYoUEZIeFNfaGxnbV9wcl9tZWQsIDMpKQpQRkh4U19obF9tZWRpYW5fZ208LSBwYXN0ZShzaWduaWYoUEZIeFNfaGxfbWVkaWFuX2dtLCAzKSkKUEZIeFNfaGxnc2RfcHJfbWVkPC0gcGFzdGUoc2lnbmlmKFBGSHhTX2hsZ3NkX3ByX21lZCwgMykpClBGSHhTX2hsX2dzZF9tZWQ8LSBwYXN0ZShzaWduaWYoUEZIeFNfaGxfZ3NkX21lZCwgMykpClBGSHhTX3ZkX2dtX3ByX21lZDwtIHBhc3RlKHNpZ25pZihQRkh4U192ZF9nbV9wcl9tZWQsIDMpKQpQRkh4U192ZF9nbV9tZWQ8LSBwYXN0ZShzaWduaWYoUEZIeFNfdmRfZ21fbWVkLCAzKSkKUEZIeFNfdmRfZ3NkX3ByX21lZDwtIHBhc3RlKHNpZ25pZihQRkh4U192ZF9nc2RfcHJfbWVkLCAzKSkKUEZIeFNfdmRfZ3NkX21lZDwtIHBhc3RlKHNpZ25pZihQRkh4U192ZF9nc2RfbWVkLCAzKSkKUEZIeFNfY2xfZ21fcHJfbWVkPC0gcGFzdGUoc2lnbmlmKFBGSHhTX2NsX2dtX3ByX21lZCwgMykpClBGSHhTX2NsX2dtX21lZDwtIHBhc3RlKHNpZ25pZihQRkh4U19jbF9nbV9tZWQsIDMpKQpgYGAKCiMjIyBQb3B1bGF0aW9uIG1lZGlhbiBlc3RpbWF0ZXMgWzk1JSBDSV0gCgp8IFBhcmFtZXRlciAgICAgICAgICAgICAgICAgICAgICB8IFByaW9yIEdNICAgICAgfCBQb3N0ZXJpb3IgR00gfCBQcmlvciAgR1NEICAgIHwgUG9zdGVyaW9yIEdTRCB8IAp8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLTp8IAp8IEhhbGYtbGlmZSAoeWVhcnMpICB8IGByIHBhc3RlKFBGSHhTX2hsZ21fcHJfbWVkKSBgIHwgICBgciBwYXN0ZShQRkh4U19obF9tZWRpYW5fZ20pIGAgICAgfCBgciAgcGFzdGUoUEZIeFNfaGxnc2RfcHJfbWVkKSBgICAgICAgICAgICB8IGByIHBhc3RlKFBGSHhTX2hsX2dzZF9tZWQpYCAgfCAKfCBITCAgWzk1JSBDSV0gIHxgciBwYXN0ZTAoIlsiLFBGSHhTX2hsZ21fcHJfbWVkXzk1Y2ksIl0iKWAgfCBgciBwYXN0ZTAoICJbIixQRkh4U19obF9tZWRpYW5fZ21fOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCJbIixQRkh4U19obGdzZF9wcl9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCAiWyIsUEZIeFNfaGxfZ3NkX21lZF85NWNpLCAiXSIpYHwKfCBWb2x1bWUgb2YgZGlzdHJpYnV0aW9uICAgIHwgYHIgcGFzdGUoUEZIeFNfdmRfZ21fcHJfbWVkKSBgIHwgICAgYHIgcGFzdGUoICBQRkh4U192ZF9nbV9tZWQpIGB8ICAgYHIgIHBhc3RlKFBGSHhTX3ZkX2dzZF9wcl9tZWQpYCAgfGByICBwYXN0ZShQRkh4U192ZF9nc2RfbWVkKWAgfCAgCnwgJFZfRCQgWzk1JSBDSV0gICAgfGByIHBhc3RlMCggIlsiLFBGSHhTX3ZkX2dtX3ByX21lZF85NWNpLCJdIilgfCBgciBwYXN0ZTAoICJbIixQRkh4U192ZF9nbV9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCJbIixQRkh4U192ZF9nc2RfcHJfbWVkXzk1Y2ksICJdIilgfCBgciBwYXN0ZTAoICAiWyIsUEZIeFNfdmRfZ3NkX21lZF85NWNpLCAiXSIpYHwgCnwgQ2xlYXJhbmNlICAgIHwgYHIgcGFzdGUoUEZIeFNfY2xfZ21fcHJfbWVkKSBgIHwgICAgYHIgcGFzdGUoICBQRkh4U19jbF9nbV9tZWQpIGB8ICAgYHIgIHBhc3RlKClgICB8YHIgIHBhc3RlKClgIHwgIAp8ICRDTCQgWzk1JSBDSV0gICAgfGByIHBhc3RlMCggIlsiLFBGSHhTX2NsX2dtX3ByX21lZF85NWNpLCJdIilgfCBgciBwYXN0ZTAoICJbIixQRkh4U19jbF9nbV9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCJbIiwgIl0iKWB8IGByIHBhc3RlMCggICJbIiwgIl0iKWB8IAogCgoKIyMjIEluZGl2aWR1YWwgUG9zdGVyaW9yIGVzdGltYXRlcyAKCnwgUGFyYW1ldGVyICAgICAgICAgICAgICAgICAgICAgIHwgIG1lZGlhbiBHTSAgWzk1JSBDSV0gW1s5OCUgQ0ldXSB8IEdNIGNhbGN1bGF0b3IgaW5wdXQgIHwgIEdTRCBpbmRpdmlkdWFsIHwKfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tOnwgCnwgSGFsZi1saWZlICh5ZWFycykgICAgICAgICAgICAgIHwgYHIgIHBhc3RlKG1lZF9obF9pLCAiWyIsY2lfbWVkX2hsX2ksIl0iLCAiW1siLGNpOThfbWVkX2hsX2ksIl1dIikgYCB8IGByICBwYXN0ZShnbV9obF9pKSBgIHwgYHIgIHBhc3RlKGdzZF9obF9pKSBgfAp8IFZvbHVtZSBvZiBkaXN0cmlidXRpb24gJFZfRCQgICB8IGByICBwYXN0ZShtZWRfVmRfaSwgIlsiLGNpX21lZF9WZF9pLCJdIiwgIltbIixjaTk4X21lZF9WZF9pLCJdXSIpIGAgfCBgciAgcGFzdGUoZ21fdmRfaSkgYCB8IGByICBwYXN0ZShnc2RfdmRfaSkgYHwgCgoKCiMjIyBTZXNzaW9uIGluZm9ybWF0aW9uCmBgYHtyIGVjaG89RkFMU0V9CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGA=